negamartin

XT V2.0 by negamartin

Sep 12th, 2015
358
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 38.78 KB | None | 0 0
  1. --XT V2.0 by negamartin
  2.  
  3. setfenv(1,setmetatable({},{__index=getfenv(1)}));
  4. local xt={};
  5. xt.version=2.0;
  6.  
  7. --Serialization
  8. function xt.escapeString(unescaped,esctab)
  9.     local escstr="";
  10.     for c in unescaped:gmatch(".") do
  11.         escstr=escstr..(esctab[c] or c);
  12.     end
  13.     return escstr;
  14. end
  15. function xt.descapeString(escaped,desctab,escchar)
  16.     local descstr="";
  17.     local descNext=false;
  18.     if escchar then --1 escape char method (more efficient)
  19.         for c in escaped:gmatch(".") do
  20.             if descNext then
  21.                 descstr=descstr..desctab[c];
  22.                 descNext=false;
  23.             else
  24.                 if c==escchar then
  25.                     descNext=true;
  26.                 else
  27.                     descstr=descstr..c;
  28.                 end
  29.             end
  30.         end
  31.     else                            --Multiple escape chars method (slower)
  32.         for c in escaped:gmatch(".") do
  33.             if descNext then
  34.                 descstr=descstr..descNext[c];
  35.                 descNext=false;
  36.             else
  37.                 descNext=desctab[c];
  38.                 if not descNext then
  39.                     descstr=descstr..c;
  40.                 end
  41.             end
  42.         end
  43.     end
  44.     return descstr;
  45. end
  46. --Build safestring escapers
  47. local char30=string.char(30);
  48. local char31=string.char(31);
  49. xt.safeEscaper={["\\"]="\\\\",["\n"]="\\n",["\r"]="\\r",[char30]="\\"..char30,[char31]="\\"..char31};
  50. xt.safeDescaper={["\\"]={["\\"]="\\",["n"]="\n",["r"]="\r",[char30]=char30,[char31]=char31},[char30]={},[char31]={}};
  51. for i=128,255 do
  52.     if i==138 then      --Will be safed into newline char
  53.         xt.safeEscaper[string.char(138)]=char31.."n";
  54.         xt.safeDescaper[char31]["n"]=string.char(138);
  55.     elseif i==141 then  --Will be safed into carriage return char
  56.         xt.safeEscaper[string.char(141)]=char31.."r";
  57.         xt.safeDescaper[char31]["r"]=string.char(141);
  58.     else
  59.         xt.safeEscaper[string.char(i)]=char30..string.char(i-128);
  60.         xt.safeDescaper[char30][string.char(i-128)]=string.char(i);
  61.     end
  62. end
  63. function xt.safeString(unsafe) return xt.escapeString(unsafe,xt.safeEscaper); end
  64. function xt.unsafeString(safe) return xt.descapeString(safe,xt.safeDescaper); end
  65. function xt.isUnsafe(str)
  66.     for c in str:gmatch(".") do
  67.         local b=c:byte();
  68.         if b==10 or b==13 or b>127 then return true; end
  69.     end
  70.     return false;
  71. end
  72. xt.nativeFuncs={};
  73. xt.serializeEscaper={[","]="|.",["="]="|-",["{"]="|[",["}"]="|]",["|"]="||"};
  74. xt.serializeDescaper={["."]=",",["-"]="=",["["]="{",["]"]="}",["|"]="|"};
  75. function xt.stringify(val,lvl,tabs,dofunc,dometa,donative)
  76.     local t=type(val);
  77.     local sval;
  78.     if t=="string" then
  79.         local pre="s";
  80.         if xt.isUnsafe(val) then val=xt.safeString(val);pre="u"; end
  81.         sval=pre..xt.escapeString(val,xt.serializeEscaper);
  82.     elseif t=="number" then
  83.         sval="n"..tostring(val);
  84.     elseif t=="boolean" then
  85.         if val then sval="bt";
  86.         else sval="bf"; end
  87.     elseif t=="table" then
  88.         if tabs[val] then   --If table has already been stringified, make a pointer to it
  89.             sval="p"..tabs[val];
  90.         else
  91.             tabs[0]=tabs[0]+1;
  92.             tabs[val]=tabs[0];
  93.             sval="{";
  94.             for k,v in pairs(val) do
  95.                 local skey,svalue;
  96.                 skey=xt.stringify(k,lvl+1,tabs,dofunc,dometa,donative);
  97.                 svalue=xt.stringify(v,lvl+1,tabs,dofunc,dometa,donative);
  98.                 sval=sval..skey.."="..svalue..",";
  99.             end
  100.             if dometa and type(getmetatable(val))=="table" then
  101.                 sval=sval.."}:"..xt.stringify(getmetatable(val),lvl+1,tabs,dofunc,dometa,donative);
  102.             else
  103.                 sval=sval.."}";
  104.             end
  105.         end
  106.     elseif t=="function" then
  107.         if dofunc then
  108.             local ok,dump=pcall(string.dump,val);
  109.             if ok then
  110.                 sval="f"..xt.escapeString(xt.safeString(dump),xt.serializeEscaper);
  111.             elseif donative then
  112.                 local funcname=false;
  113.                 funcname=xt.nativeFuncs[val];   --Check for previously serialized nativefuncs
  114.                 if funcname then                --And test if they still exist where they should
  115.                     local test=_G or (type(getfenv)=="function" and getfenv(1));
  116.                     for word in funcname:gmatch("[^%.]+") do
  117.                         if type(test)~="table" then test=false;break; end
  118.                         test=test[word];
  119.                         if type(test)~="table" and type(test)~="function" then test=false;break; end
  120.                     end
  121.                     if not test then
  122.                         xt.nativeFuncs[val]=nil;
  123.                         funcname=false;
  124.                     end
  125.                 end
  126.                 if not funcname then            --If the nativefunc was not serialized before, find it in _G
  127.                     local donetabs={};
  128.                     function inspectTab(tab)
  129.                         for k,v in pairs(tab) do
  130.                             if type(k)=="string" then
  131.                                 if v==val then return k;
  132.                                 elseif type(v)=="table" then
  133.                                     if not donetabs[v] then
  134.                                         donetabs[v]=true;
  135.                                         local result=inspectTab(v);
  136.                                         if result then
  137.                                             return k.."."..result;
  138.                                         end
  139.                                     end
  140.                                 end
  141.                             end
  142.                         end
  143.                     end
  144.                     funcname=inspectTab(_G);
  145.                     xt.nativeFuncs[val]=funcname;   --And save it for future serializations
  146.                 end
  147.                 if funcname then
  148.                     sval="j"..funcname;
  149.                 else
  150.                     error("Could not serialize native function ["..tostring(val).."], nested "..(lvl-1).." tables deep",lvl+1);
  151.                 end
  152.             else
  153.                 error("Serializing native functions is not enabled",lvl+1);
  154.             end
  155.         else error("Serializing functions is not enabled",lvl+1); end
  156.     elseif t=="nil" then
  157.         sval="l";
  158.     else error("Cannot serialize type "..tostring(t)..", nested "..(lvl-1).." tables",lvl+1); end
  159.     return sval;
  160. end
  161. function xt.valuefy(str,lvl,tabs,dofunc,dometa,donative)
  162.     local pre=str:sub(1,1);
  163.     local sval=str:sub(2).."";
  164.     local val;
  165.     if pre=="s" then        --Safe string
  166.         val=xt.descapeString(sval,xt.serializeDescaper,"|");
  167.     elseif pre=="u" then    --Unsafe string
  168.         val=xt.unsafeString(xt.descapeString(sval,xt.serializeDescaper,"|"));
  169.     elseif pre=="n" then    --Number
  170.         val=tonumber(sval);
  171.     elseif pre=="b" then    --Boolean
  172.         val=sval=="t";
  173.     elseif pre=="{" then    --Table
  174.         val={};
  175.         tabs[0]=tabs[0]+1;
  176.         tabs[tabs[0] ]=val;
  177.         local blvl=1;
  178.         local lastStart=1;
  179.         local cur=0;
  180.         local equal=false;
  181.         local metatab=false;
  182.         for c in sval:gmatch(".") do
  183.             cur=cur+1;
  184.             if c=="{" then blvl=blvl+1;
  185.             elseif c=="}" then blvl=blvl-1;
  186.             elseif c=="=" and blvl==1 then
  187.                 equal=cur;
  188.             elseif c=="," and blvl==1 then
  189.                 local key,value;
  190.                 key=xt.valuefy(sval:sub(lastStart,equal-1).."",lvl+1,tabs,dofunc,dometa,donative);
  191.                 value=xt.valuefy(sval:sub(equal+1,cur-1).."",lvl+1,tabs,dofunc,dometa,donative);
  192.                 val[key]=value;
  193.                 lastStart=cur+1;
  194.             elseif blvl==0 and c==":" then
  195.                 if dometa then
  196.                     metatab=xt.valuefy(sval:sub(cur+1).."",lvl+1,tabs,dofunc,dometa,donative);
  197.                     break;
  198.                 else error("Unserializing metatables is not enabled",lvl+1); end
  199.             end
  200.         end
  201.         if metatab then setmetatable(val,metatab); end
  202.     elseif pre=="p" then    --table Pointer
  203.         val=tabs[tonumber(sval)];
  204.     elseif pre=="f" then    --Function
  205.         if dofunc then
  206.             val=loadstring(xt.unsafeString(xt.descapeString(sval,xt.serializeDescaper,"|")));
  207.         else error("Unserializing functions is not enabled",lvl+1); end
  208.     elseif pre=="j" then    --Java function
  209.         if donative then
  210.             local curval=_G or (type(getfenv)=="function" and getfenv(1));
  211.             for word in sval:gmatch("[^%.]+") do
  212.                 if type(curval)~="table" then curval=false;break; end
  213.                 curval=curval[word];
  214.                 if type(curval)~="table" and type(curval)~="function" then curval=false;break; end
  215.             end
  216.             if type(curval)=="function" and not pcall(string.dump,curval) then
  217.                 val=curval;
  218.             else error("Could not unserialize native function["..sval.."], nested "..(lvl-1).." tables",lvl+1); end
  219.         else error("Unserializing native functions is not enabled",lvl+1); end
  220.     elseif pre=="l" then    --niL
  221.     else error("Unknown prefix "..tostring(pre)..", nested "..(lvl-1).." tables",lvl+1); end
  222.     return val;
  223. end
  224. function xt.serialize(val,df,dm,dn) return xt.stringify(val,1,{[0]=0},df,dm,dn); end
  225. function xt.unserialize(str,df,dm,dn) return xt.valuefy(str,1,{[0]=0},df,dm,dn); end
  226. function xt.fserialize(val,df,dm,dn) return xt.stringify(val,1,{[0]=0},not df,not dm,not dn); end
  227. function xt.funserialize(str,df,dm,dn) return xt.valuefy(str,1,{[0]=0},not df,not dm,not dn); end
  228.  
  229. --Saving
  230. function xt.setUser(user,lvl)
  231.     if type(user)~="string" then error("User must be a string",2);
  232.     elseif user=="global" then error("User cant be \"global\"",2); end
  233.     local prevenv=getfenv(lvl or 2);
  234.     if rawget(prevenv,"___Xt__UsEr___") then
  235.         rawset(prevenv,"___Xt__UsEr___",user);
  236.     else
  237.         setfenv(lvl or 2,setmetatable({___Xt__UsEr___=user},{__index=prevenv,__newindex=prevenv}));
  238.     end
  239. end
  240. function xt.loadValue(user,name)
  241.     if fs.isDir("/xtdata") then
  242.         if type(user)~="string" then error("Attempt to load value with invalid user (maybe call xt.setUser?)",2); end
  243.         user="/xtdata/"..user.."/";
  244.         if fs.isDir(user) then
  245.             if fs.exists(user..name) and not fs.isDir(user..name) then
  246.                 local handle=fs.open(user..name,"r");
  247.                 local val=handle.readLine();
  248.                 handle.close();
  249.                 return xt.unserialize(val);
  250.             end
  251.         end
  252.     end
  253. end
  254. function xt.saveValue(user,name,val)
  255.     if type(user)~="string" then error("Attempt to save value with invalid user (maybe call xt.setUser?)",2); end
  256.     local sval=xt.serialize(val);
  257.     if not fs.isDir("/xtdata") then
  258.         fs.delete("/xtdata");
  259.         fs.makeDir("/xtdata");
  260.     end
  261.     if not fs.isDir("/xtdata/"..user) then
  262.         fs.delete("/xtdata/"..user);
  263.         fs.makeDir("/xtdata/"..user);
  264.     end
  265.     if fs.isDir("/xtdata/"..user.."/"..name) then
  266.         fs.delete("/xtdata/"..user.."/"..name);
  267.     end
  268.     local h=fs.open("/xtdata/"..user.."/"..name,"w");
  269.     h.writeLine(sval);
  270.     h.close();
  271. end
  272. function xt.deleteValue(name,user)
  273.     if user==nil then
  274.         user=getfenv(2).___Xt__UsEr___;
  275.     elseif user==true then
  276.         user="global";
  277.     end
  278.     if type(user)~="string" then error("Attempt to delete value with invalid user (maybe call xt.setUser?)",2); end
  279.     xt.values[user][name]=nil;
  280.     local delUser=#xt.values[user]==0;
  281.     if fs.isDir("/xtdata") then
  282.         user="/xtdata/"..user.."/";
  283.         if fs.isDir(user) then
  284.             fs.delete(user..name);
  285.         end
  286.         if delUser then fs.delete(user); end
  287.     end
  288.     if delUser then
  289.         xt.values[user]=nil;
  290.     end
  291. end
  292. xt.values={global={}};
  293. setmetatable(xt,{__newindex=function(_,k,v)
  294.     if xt.values.global[k]~=nil then
  295.         if v==nil then
  296.             xt.deleteValue(k,"global");
  297.         elseif xt.values.global[k]~=v then
  298.             xt.saveValue("global",k,v);
  299.             xt.values.global[k]=v;
  300.         end
  301.         return;
  302.     end
  303.     local user=getfenv(2).___Xt__UsEr___;
  304.     if xt.values[user] then
  305.         if xt.values[user][k]~=nil then
  306.             if v==nil then
  307.                 xt.deleteValue(k,user);
  308.             elseif xt.values[user][k]~=v then
  309.                 xt.saveValue(user,k,v);
  310.                 xt.values[user][k]=v;
  311.             end
  312.             return;
  313.         end
  314.     end
  315.     rawset(xt,k,v);
  316. end,__index=function(_,k)
  317.     if xt.values.global[k]~=nil then
  318.         return xt.values.global[k];
  319.     end
  320.     local user=getfenv(2).___Xt__UsEr___;
  321.     if xt.values[user] and xt.values[user][k]~=nil then
  322.         return xt.values[user][k];
  323.     end
  324. end});
  325. function xt.addValue(name,val,global,user)
  326.     if user==nil then
  327.         user=getfenv(2).___Xt__UsEr___;
  328.     end
  329.     if type(user)~="string" then error("Attempt to add value with invalid user (maybe call xt.setUser?)",2); end
  330.     if global then user="global"; end
  331.     if type(name)~="string" then error("Value name must be a string",2);
  332.     elseif user~="global" and xt.values.global[name]~=nil then error("A global value named \""..name.."\" is already registered",2);
  333.     --elseif xt.values[user] and xt.values[user][name]~=nil then error("Value \""..name.."\" is already registered to user \""..user.."\"",2);
  334.     elseif rawget(xt,name)~=nil then error("xt."..tostring(name).." already exists as a non-value key",2);
  335.     end
  336.     if type(xt.values[user])~="table" then xt.values[user]={}; end
  337.     local prevVal=xt.loadValue(user,name);
  338.     if prevVal==nil then
  339.         if val~=nil then
  340.             xt.saveValue(user,name,val);
  341.             xt.values[user][name]=val;
  342.         end
  343.         return true;
  344.     else
  345.         xt.values[user][name]=prevVal;
  346.         return false;
  347.     end
  348. end
  349. function xt.save(name)
  350.     local user=getfenv(2).___Xt__UsEr___;
  351.     if type(user)~="string" then error("Attempt to save value with invalid user (maybe call xt.setUser?)",2);
  352.     elseif type(name)~="string" then error("Name should be a string",2); end
  353.     if xt.values.global[name]~=nil then
  354.         xt.saveValue("global",name,xt.values.global[name]);
  355.     elseif xt.values[user][name]~=nil then
  356.         xt.saveValue(user,name,xt.values[user][name]);
  357.     end
  358. end
  359.  
  360. --Stackgroup system
  361. xt.stackgroup={};
  362. xt.priorities={};
  363. xt.stacknames={};
  364. function xt.addStack(stackgroup,priorities,stacknames,name,priority)
  365.     priority=priority or 0;
  366.     if stackgroup[name] then error("Stack "..name.." already exists",2); end
  367.     local myIndex=false;
  368.     for i,p in ipairs(priorities) do
  369.         if p<priority then myIndex=i;break; end
  370.     end
  371.     myIndex=myIndex or (#priorities+1);
  372.     table.insert(priorities,myIndex,priority);
  373.     table.insert(stacknames,myIndex,name);
  374.     stackgroup[name]={};
  375.     return true;
  376. end
  377. function xt.pushStack(stackgroup,sname,handler)
  378.     local stack=stackgroup[sname];
  379.     if stack then
  380.         stack[#stack+1]=handler;
  381.     else error("Attempt to push unexisting stack "..tostring(sname),2); end
  382.     return true;
  383. end
  384. function xt.popStack(stackgroup,sname)
  385.     local stack=stackgroup[sname];
  386.     if not stack then error("Attempt to pop unexisting stack "..tostring(sname),2); end
  387.     local h=stack[#stack];
  388.     stack[#stack]=nil;
  389.     return h;
  390. end
  391. function xt.peekStack(stackgroup,sname)
  392.     local stack=stackgroup[sname];
  393.     if not stack then error("Attempt to peek unexisting stack "..tostring(sname),2); end
  394.     return stack[#stack];
  395. end
  396. function xt.peekAllStacks(stackgroup,stacknames)
  397.     local i=1;
  398.     return function()
  399.         while true do
  400.             local name=stacknames[i];
  401.             if name==nil then return; end
  402.             local stack=stackgroup[name];
  403.             i=i+1;
  404.             if #stack~=0 then return name,stack[#stack]; end
  405.         end
  406.     end;
  407. end
  408. function xt.callStackgroup(stackgroup,stacknames,...)
  409.     for i=1,#stacknames do
  410.         local stack=stackgroup[stacknames[i]];
  411.         if #stack~=0 then stack[#stack](...); end
  412.     end
  413. end
  414. function xt.addStackgroup(name)
  415.     local stackgroup={};
  416.     local priorities={};
  417.     local stacknames={};
  418.     xt.stackgroup[name]=stackgroup;
  419.     xt.priorities[name]=priorities;
  420.     xt.stacknames[name]=stacknames;
  421.     --Main functions
  422.     xt["add"..name]=function(n,p)
  423.         return xt.addStack(stackgroup,priorities,stacknames,n,p);
  424.     end
  425.     xt["push"..name]=function(n,h)
  426.         return xt.pushStack(stackgroup,n,h);
  427.     end
  428.     xt["pop"..name]=function(n)
  429.         return xt.popStack(stackgroup,n);
  430.     end
  431.     xt["peek"..name]=function(n)
  432.         return xt.peekStack(stackgroup,n);
  433.     end
  434.     xt["peekAll"..name]=function()
  435.         return xt.peekAllStacks(stackgroup,stacknames);
  436.     end
  437.     xt["call"..name]=function(...)
  438.         return xt.callStackgroup(stackgroup,stacknames,...);
  439.     end
  440.     --Helper functions
  441.     xt["check"..name]=function(n,dp)
  442.         if stackgroup[n]==nil then
  443.             return xt.addStack(stackgroup,priorities,stacknames,n,dp);
  444.         end
  445.         return false;
  446.     end
  447.     xt["fpush"..name]=function(n,h,dp)
  448.         if stackgroup[n]==nil then
  449.             xt.addStack(stackgroup,priorities,stacknames,n,dp);
  450.         end
  451.         return xt.pushStack(stackgroup,n,h);
  452.     end
  453.     xt["delete"..name]=function(n)
  454.         if stackgroup[n] then
  455.             for i,tn in ipairs(stacknames) do
  456.                 if tn==n then
  457.                     table.remove(priorities,i);
  458.                     table.remove(stacknames,i);
  459.                     break;
  460.                 end
  461.             end
  462.             stackgroup[n]=nil;
  463.         end
  464.     end
  465. end
  466.  
  467. --Program restoration
  468. function xt.enableRestoration(path,prevdo)
  469.     path=path or shell.getRunningProgram();
  470.     if type(path)~="string" then error("Expected program pathname",2);
  471.     elseif not fs.exists(path) or fs.isDir(path) then error("Pathname must be a file",2);
  472.     elseif prevdo and prevdo~="p" and prevdo~="b" and prevdo~="a" and prevdo~="i" then error("Invalid old startup handling, "..tostring(prevdo),2); end
  473.     xt.disableRestoration();
  474.     if fs.exists("/startup") then
  475.         if fs.isDir("/startup") then
  476.             prevdo="i";
  477.         else
  478.             if not prevdo then
  479.                 print("What do you wish to do with the previous startup program?");
  480.                 print("[P] Run it alongside this program on startup");
  481.                 print("[B] Run it before this program on startup");
  482.                 print("[A] Run it after this program on startup");
  483.                 print("[I] Don't run it at all, just restore it after");
  484.                 while true do
  485.                     local ev,k=os.pullEvent("key");
  486.                     if k==keys.p then prevdo="p";break;     --Parallel
  487.                     elseif k==keys.b then prevdo="b";break; --Before
  488.                     elseif k==keys.a then prevdo="a";break; --After
  489.                     elseif k==keys.i then prevdo="i";break; --Ignore
  490.                     end
  491.                 end
  492.                 sleep(0);   --Clear event queue, including key pressed
  493.             end
  494.         end
  495.         if fs.exists("/xt_active_startup") then
  496.             local i=1;
  497.             while true do
  498.                 if not fs.exists("/xt_startup_backup_"..i) then break; end
  499.                 i=i+1;
  500.             end
  501.             fs.move("/xt_active_startup","/xt_startup_backup_"..i);
  502.         end
  503.         fs.move("/startup","/xt_active_startup");
  504.     else prevdo="i"; end
  505.     local contents;
  506.     if prevdo=="p" then
  507.         contents=[[parallel.waitForAll(function()shell.run("/xt_active_startup")end,function()shell.run("]]..path..[[")end)]];
  508.     elseif prevdo=="b" then
  509.         contents=[[local ok,err=pcall(shell.run,"/xt_active_startup")if not ok then printError(tostring(err))sleep(2) end shell.run("]]..path..[[")]];
  510.     elseif prevdo=="a" then
  511.         contents=[[local ok,err=pcall(shell.run,"]]..path..[[")if not ok then printError(tostring(err))sleep(2) end shell.run("/xt_active_startup")]];
  512.     elseif prevdo=="i" then
  513.         contents=[[shell.run("]]..path..[[");]];
  514.     else error("what?"); end
  515.     local handle=fs.open("/startup","w");
  516.     handle.writeLine("--XT's restore-on-startup program");
  517.     handle.writeLine("--DO NOT CHANGE OR REMOVE THESE COMMENTS");
  518.     handle.writeLine("--Running "..path);
  519.     if prevdo=="i" then handle.writeLine("--and nothing else");
  520.     else handle.writeLine("--and /xt_active_startup"); end
  521.     handle.writeLine(contents);
  522.     handle.close();
  523.     if not fs.exists("/restore") then
  524.         local handle=fs.open("/restore","w");
  525.         handle.writeLine("--XT's easy startup disabler program");
  526.         handle.writeLine("--DO NOT CHANGE OR REMOVE THESE COMMENTS");
  527.         handle.writeLine([[if type(xt)=="table" and type(xt.disableRestoration)=="function" then xt.disableRestoration(); else printError("Failed to restore"); end]]);
  528.         handle.close();
  529.     end
  530.     return true;
  531. end
  532. function xt.disableRestoration()
  533.     local didDo=false;
  534.     if fs.exists("/startup") and not fs.isDir("/startup") then
  535.         local handle=fs.open("/startup","r");
  536.         local first=handle.readLine();
  537.         local second=handle.readLine();
  538.         handle.close();
  539.         if first=="--XT's restore-on-startup program" and second=="--DO NOT CHANGE OR REMOVE THESE COMMENTS" then
  540.             fs.delete("/startup");
  541.             didDo=true;
  542.         end
  543.     end
  544.     if fs.exists("/restore") and not fs.isDir("/restore") then
  545.         local handle=fs.open("/restore","r");
  546.         local first=handle.readLine();
  547.         local second=handle.readLine();
  548.         handle.close();
  549.         if first=="--XT's easy startup disabler program" and second=="--DO NOT CHANGE OR REMOVE THESE COMMENTS" then
  550.             fs.delete("/restore");
  551.         end
  552.     end
  553.     if fs.exists("/xt_active_startup") and not fs.exists("/startup") then
  554.         fs.move("/xt_active_startup","/startup");
  555.     end
  556.     return didDo;
  557. end
  558.  
  559. --Turtle functions that dont require turtle api
  560. xt.fc={
  561.     south=0,
  562.     west=1,
  563.     north=2,
  564.     east=3,
  565.     [0]="south",
  566.     [1]="west",
  567.     [2]="north",
  568.     [3]="east",
  569.     ["z+"]=0,
  570.     ["x-"]=1,
  571.     ["z-"]=2,
  572.     ["x+"]=3,
  573.     zplus=0,
  574.     xminus=1,
  575.     zminus=2,
  576.     xplus=3,
  577. };
  578. function xt.invertFace(facing)
  579.     return (facing+2)%4;
  580. end
  581. function xt.getFX(f)
  582.     f=f or xt.f;
  583.     if f==nil then error("F must be a number",2);
  584.     elseif f==1 then return -1;
  585.     elseif f==3 then return 1;
  586.     else return 0; end
  587. end
  588. function xt.getFZ(f)
  589.     f=f or xt.f;
  590.     if f==nil then error("F must be a number",2);
  591.     elseif f==0 then return 1;
  592.     elseif f==2 then return -1;
  593.     else return 0; end
  594. end
  595.  
  596. --Turtle functions that do require turtle api
  597. if turtle then
  598.     --Set values
  599.     ___Xt__UsEr___="xt";
  600.     xt.addValue("x",0,true);
  601.     xt.addValue("y",0,true);
  602.     xt.addValue("z",0,true);
  603.     xt.addValue("f",0,true);
  604.    
  605.     --Movement handling
  606.     xt.addStackgroup("Premove");
  607.     xt.addStackgroup("Preturn");
  608.     xt.addStackgroup("Refuel");
  609.     xt.addPremove("err",0);
  610.     xt.pushPremove("err",function()error("Attempt to move without reloading stacks (maybe call xt.setTurtleUser?)");end);
  611.     xt.addPreturn("err",0);
  612.     xt.pushPreturn("err",function()error("Attempt to turn without reloading stacks (maybe call xt.setTurtleUser?)");end);
  613.     xt.addRefuel("err",0);
  614.     xt.pushRefuel("err",function()error("Refueled without reloading stacks (maybe call xt.setTurtleUser?)");end);
  615.     --Position saving
  616.     xt.addValue("moveData",{false,0});
  617.     function xt.doMove(dir,mult)
  618.         if dir=="fw" then
  619.             if xt.getFX()==0 then
  620.                 xt.z=xt.z+xt.getFZ()*mult;
  621.             else
  622.                 xt.x=xt.x+xt.getFX()*mult;
  623.             end
  624.         elseif dir=="bk" then
  625.             if xt.getFX()==0 then
  626.                 xt.z=xt.z-xt.getFZ()*mult;
  627.             else
  628.                 xt.x=xt.x-xt.getFX()*mult;
  629.             end
  630.         elseif dir=="up" then
  631.             xt.y=xt.y+mult;
  632.         elseif dir=="dn" then
  633.             xt.y=xt.y-mult;
  634.         end
  635.     end
  636.     function xt.premoveSaving(dir)
  637.         if xt.moveData[1] then xt.correctPosition(); end
  638.         xt.moveData[2]=xt.getFuelLevel();
  639.         xt.moveData[1]=dir;
  640.         xt.save("moveData");
  641.     end
  642.     function xt.postmoveSaving(dir,ok)
  643.         if ok then
  644.             xt.doMove(dir,1);
  645.         end
  646.         xt.moveData[1]=false;
  647.         xt.save("moveData");
  648.     end
  649.     function xt.preturnSaving(dir)
  650.         if dir=="r" then xt.f=(xt.f+1)%4;
  651.         elseif dir=="l" then xt.f=(xt.f-1)%4;
  652.         else error("suspicious..."); end
  653.     end
  654.     function xt.preturnChecking(dir)
  655.         xt.wasTurning=xt.wasTurning+1;
  656.     end
  657.     function xt.postturnChecking(dir)
  658.         xt.wasTurning=xt.wasTurning-1;
  659.     end
  660.     xt.fuelUpdated=false;
  661.     function xt.postmoveFuel(dir,ok)
  662.         if ok and xt.fuelUpdated then
  663.             xt.fuelUpdated=xt.fuelUpdated-1;
  664.         end
  665.     end
  666.     function xt.refuelFuel()
  667.         xt.fuelUpdated=false;
  668.     end
  669.     function xt.reloadStacks(dontsave,checkturns)
  670.         xt.stackgroup={};
  671.         xt.priorities={};
  672.         xt.stacknames={};
  673.         xt.addStackgroup("Premove");
  674.         xt.addStackgroup("Forcemove");
  675.         xt.addStackgroup("Postmove");
  676.         xt.addStackgroup("Preturn");
  677.         xt.addStackgroup("Postturn");
  678.         xt.addStackgroup("Refuel");
  679.         if not dontsave then
  680.             xt.addPremove("pos_save",100);
  681.             xt.pushPremove("pos_save",xt.premoveSaving);
  682.             xt.addPostmove("pos_save",100);
  683.             xt.pushPostmove("pos_save",xt.postmoveSaving);
  684.             xt.addPreturn("face_save",100);
  685.             xt.pushPreturn("face_save",xt.preturnSaving);
  686.         end
  687.         if checkturns then
  688.             xt.addValue("wasTurning",0);
  689.             xt.addPreturn("face_check",100);
  690.             xt.pushPreturn("face_check",xt.preturnChecking);
  691.             xt.addPostturn("face_check",100);
  692.             xt.pushPostturn("face_check",xt.postturnChecking);
  693.         else
  694.             xt.deleteValue("wasTurning");
  695.         end
  696.         xt.addPostmove("quick_fuel",90);
  697.         xt.pushPostmove("quick_fuel",xt.postmoveFuel);
  698.         xt.addRefuel("quick_fuel",90);
  699.         xt.pushRefuel("quick_fuel",xt.refuelFuel);
  700.     end
  701.     function xt.setTurtleUser(user,dontsave,checkturns)
  702.         xt.setUser(user,3);
  703.         xt.reloadStacks(dontsave,checkturns);
  704.     end
  705.    
  706.     --Movement functions
  707.     function xt.move(count,mfunc,dir,invfunc,invdir,force,...)
  708.         count=count or 1;
  709.         if count<0 then return xt.move(-count,invfunc,invdir,mfunc,dir,force,...); end
  710.         for i=1,count do
  711.             xt.callPremove(dir,...);
  712.             local ok=true;
  713.             if force then
  714.                 while not mfunc() do
  715.                     xt.callForcemove(dir,...);
  716.                 end
  717.             else ok=mfunc(); end
  718.             xt.callPostmove(dir,ok,...);
  719.             if not ok then return false; end
  720.         end
  721.         return true;
  722.     end
  723.     function xt.turn(count,tfunc,dir,invfunc,invdir,...)
  724.         count=count or 1;
  725.         if count<0 then return xt.turn(-count,invfunc,invdir,tfunc,dir,...); end
  726.         for i=1,count do
  727.             xt.callPreturn(dir,...);
  728.             tfunc();
  729.             xt.callPostturn(dir,...);
  730.         end
  731.         return true;
  732.     end
  733.    
  734.     --Movement shortcuts
  735.     function xt.fw(count,...) return xt.move(count,xt.native.forward,"fw",xt.native.back,"bk",false,...); end
  736.     function xt.bk(count,...) return xt.move(count,xt.native.back,"bk",xt.native.forward,"fw",false,...); end
  737.     function xt.up(count,...) return xt.move(count,xt.native.up,"up",xt.native.down,"dn",false,...); end
  738.     function xt.dn(count,...) return xt.move(count,xt.native.down,"dn",xt.native.up,"up",false,...); end
  739.     function xt.ffw(count,...) return xt.move(count,xt.native.forward,"fw",xt.native.back,"bk",true,...); end
  740.     function xt.fbk(count,...) return xt.move(count,xt.native.back,"bk",xt.native.forward,"fw",true,...); end
  741.     function xt.fup(count,...) return xt.move(count,xt.native.up,"up",xt.native.down,"dn",true,...); end
  742.     function xt.fdn(count,...) return xt.move(count,xt.native.down,"dn",xt.native.up,"up",true,...); end
  743.     function xt.left(count,...) return xt.turn(count,xt.native.turnLeft,"l",xt.native.turnRight,"r",...); end
  744.     function xt.right(count,...) return xt.turn(count,xt.native.turnRight,"r",xt.native.turnLeft,"l",...); end
  745.    
  746.     --Facing management
  747.     function xt.quickTurn(dist)
  748.         dist=dist%4;
  749.         if dist==0 then
  750.         elseif dist==1 then xt.right();
  751.         elseif dist==2 then xt.right(2);
  752.         elseif dist==3 then xt.left();
  753.         else error("what?"); end
  754.         return true;
  755.     end
  756.     function xt.face(nf)
  757.         if nf==nil then return false,"Not enough arguments"; end
  758.         return xt.quickTurn(nf-xt.f);
  759.     end
  760.    
  761.     --Position management
  762.     function xt.gotoX(nx)
  763.         if nx>xt.x+0.1 then xt.face(3) elseif nx<xt.x-0.1 then xt.face(1); else return true; end
  764.         local dif=math.abs(nx-xt.x);
  765.         return xt.fw(dif);
  766.     end
  767.     function xt.gotoZ(nz)
  768.         if nz>xt.z+0.1 then xt.face(0) elseif nz<xt.z-0.1 then xt.face(2); else return true; end
  769.         local dif=math.abs(nz-xt.z);
  770.         return xt.fw(dif);
  771.     end
  772.     function xt.gotoXZ(nx,nz)
  773.         local fx=xt.getFX();
  774.         local fz=xt.getFZ();
  775.         if (fz==1 and nz>xt.z) or (fz==-1 and nz<xt.z) or (fx==1 and nx<xt.x) or (fx==-1 and nx>xt.x) then
  776.             xt.gotoZ(nz);
  777.             xt.gotoX(nx);
  778.         else
  779.             xt.gotoX(nx);
  780.             xt.gotoZ(nz);
  781.         end
  782.     end
  783.     function xt.gotoY(ny)
  784.         local func;
  785.         if ny>xt.y then func=xt.up; elseif ny<xt.y then func=xt.dn; else return true; end
  786.         local dif=math.abs(ny-xt.y);
  787.         return func(dif);
  788.     end
  789.     function xt.gotoXZY(nx,ny,nz)
  790.         xt.gotoXZ(nx,nz);
  791.         xt.gotoY(ny);
  792.     end
  793.     function xt.gotoYXZ(nx,ny,nz)
  794.         xt.gotoY(ny);
  795.         xt.gotoXZ(nx,nz);
  796.     end
  797.  
  798.     function xt.fgotoX(nx)
  799.         if nx>xt.x+0.1 then xt.face(3) elseif nx<xt.x-0.1 then xt.face(1); else return true; end
  800.         local dif=math.abs(nx-xt.x);
  801.         return xt.ffw(dif);
  802.     end
  803.     function xt.fgotoZ(nz)
  804.         if nz>xt.z+0.1 then xt.face(0) elseif nz<xt.z-0.1 then xt.face(2); else return true; end
  805.         local dif=math.abs(nz-xt.z);
  806.         return xt.ffw(dif);
  807.     end
  808.     function xt.fgotoXZ(nx,nz)
  809.         local fx=xt.getFX();
  810.         local fz=xt.getFZ();
  811.         if (fz==1 and nz>xt.z) or (fz==-1 and nz<xt.z) or (fx==1 and nx<xt.x) or (fx==-1 and nx>xt.x) then
  812.             xt.fgotoZ(nz);
  813.             xt.fgotoX(nx);
  814.         else
  815.             xt.fgotoX(nx);
  816.             xt.fgotoZ(nz);
  817.         end
  818.     end
  819.     function xt.fgotoY(ny)
  820.         local func;
  821.         if ny>xt.y then func=xt.fup; elseif ny<xt.y then func=xt.fdn; else return true; end
  822.         local dif=math.abs(ny-xt.y);
  823.         return func(dif);
  824.     end
  825.     function xt.fgotoXZY(nx,ny,nz)
  826.         xt.fgotoXZ(nx,nz);
  827.         xt.fgotoY(ny);
  828.     end
  829.     function xt.fgotoYXZ(nx,ny,nz)
  830.         xt.fgotoY(ny);
  831.         xt.fgotoXZ(nx,nz);
  832.     end
  833.    
  834.     function xt.navigate(coord,goal)
  835.         local movePlus=true;
  836.         if coord=="x" then
  837.             if goal<xt.x then
  838.                 xt.face(xt.fc.xminus);
  839.                 movePlus=false;
  840.             elseif goal>xt.x then
  841.                 xt.face(xt.fc.xplus);
  842.                 movePlus=true;
  843.             else return; end
  844.         elseif coord=="z" then
  845.             if goal<xt.z then
  846.                 xt.face(xt.fc.zminus);
  847.                 movePlus=false;
  848.             elseif goal>xt.z then
  849.                 xt.face(xt.fc.zplus);
  850.                 movePlus=true;
  851.             else return; end
  852.         else error("Invalid navigate coord",2); end
  853.         while (movePlus and xt[coord]-0.1<goal) or (not movePlus and xt[coord]-0.1>goal) do
  854.             while xt.dn() do end
  855.             while not xt.fw() do
  856.                 while not xt.up() do
  857.                     while not xt.bk() do
  858.                         xt.dn();
  859.                     end
  860.                 end
  861.             end
  862.         end
  863.     end
  864.     --[[function xt.nav(coord,goal) --Untested method
  865.         local moveCount;
  866.         xt.correctPosition();
  867.         if coord=="x" then
  868.             if goal>xt.x then
  869.                 xt.face(xt.fc.xplus);
  870.                 moveCount=goal-xt.x;
  871.             elseif goal<xt.x then
  872.                 xt.face(xt.fc.xminus);
  873.                 moveCount=xt.x-goal;
  874.             else return true; end
  875.         elseif coord=="z" then
  876.             if goal>xt.z then
  877.                 xt.face(xt.fc.zplus);
  878.                 moveCount=goal-xt.z;
  879.             elseif goal<xt.z then
  880.                 xt.face(xt.fc.zminus);
  881.                 moveCount=xt.z-goal;
  882.             else return true; end
  883.         else error("Invalid coord "..tostring(coord),2); end
  884.         local counter=1;
  885.         while counter<=moveCount do
  886.             while xt.dn() do end
  887.             while not xt.fw() do
  888.                 while not xt.up() do
  889.                     while not xt.bk() do
  890.                         while not xt.dn() do
  891.                             sleep(0.2);
  892.                         end
  893.                     end
  894.                     counter=counter-1;
  895.                 end
  896.             end
  897.             counter=counter+1;
  898.         end
  899.         return true;
  900.     end]]
  901.     function xt.navXZ(nx,nz)
  902.         local fx=xt.getFX();
  903.         local fz=xt.getFZ();
  904.         if (fz==1 and nz>xt.z) or (fz==-1 and nz<xt.z) or (fx==1 and nx<xt.x) or (fx==-1 and nx>xt.x) then
  905.             xt.navigate("z",nz);
  906.             xt.navigate("x",nx);
  907.         else
  908.             xt.navigate("x",nx);
  909.             xt.navigate("z",nz);
  910.         end
  911.     end
  912.    
  913.     --Orientation functions
  914.     function xt.locateGPS()
  915.         local tx;
  916.         local ty;
  917.         local tz;
  918.         tx,ty,tz=gps.locate();
  919.         if tx==nil or ty==nil or tz==nil then return false; end
  920.         xt.x=tx;
  921.         xt.z=tz;
  922.         xt.y=ty;
  923.         return true;
  924.     end
  925.     function xt.orientGPS(forward,back,donealready) --Orient facing using
  926.         if xt.getFuelLevel()~="unlimited" then
  927.             if xt.getFuel()<2 then return false,"Not enough fuel"; end
  928.         end
  929.         if donealready==nil then donealready=false; end
  930.         if forward==nil then forward=xt.fw; end
  931.         if back==nil then back=xt.bk; end
  932.         local tx;
  933.         local tz;
  934.         if not xt.locate() then return false,"Could not reach GPS"; end
  935.         tx=xt.x;tz=xt.z;
  936.         if not forward() then
  937.             if donealready then return false,"Could not go forward";
  938.             else return xt.calibrateGPS(back,forward,true); end
  939.         end
  940.         if not xt.locate() then back(); return false,"Could not reach GPS"; end
  941.         local dx=xt.x-tx;
  942.         local dz=xt.z-tz;
  943.         if donealready then dx=-dx;dz=-dz; end
  944.         if dz==1 then xt.f=0;
  945.         elseif dz==-1 then xt.f=2;
  946.         elseif dx==1 then xt.f=3;
  947.         elseif dx==-1 then xt.f=1;
  948.         end
  949.         back();
  950.         xt.wasTurning=0;
  951.         return true;
  952.     end
  953.     --Uses an inspected table of a torch, lever, ladder, sign or button with a known direction relative to the turtle to orient
  954.     --Dir must be "front", "left", "right" or "back"
  955.     function xt.orientTorch(tab,dir)
  956.         local tdir;
  957.         local meta=tab.metadata;
  958.         local block=tab.name;
  959.         if block=="minecraft:torch" or block=="minecraft:redstone_torch" or block=="minecraft:lever" or
  960.                 block=="minecraft:stone_button" or block=="minecraft:wooden_button" then
  961.             if meta==1 then tdir=xt.fc.xplus;
  962.             elseif meta==2 then tdir=xt.fc.xminus;
  963.             elseif meta==3 then tdir=xt.fc.zplus;
  964.             elseif meta==4 then tdir=xt.fc.zminus;
  965.             else return false; end
  966.         elseif block=="minecraft:ladder" or block=="minecraft:wall_sign" then
  967.             if meta==5 then tdir=xt.fc.xplus;
  968.             elseif meta==4 then tdir=xt.fc.xminus;
  969.             elseif meta==3 then tdir=xt.fc.zplus;
  970.             elseif meta==2 then tdir=xt.fc.zminus;
  971.             else return false; end
  972.         else return false; end
  973.         if dir=="front" then xt.f=tdir;
  974.         elseif dir=="back" then xt.f=(tdir+2)%4;
  975.         elseif dir=="left" then xt.f=(tdir+1)%4;
  976.         elseif dir=="right" then xt.f=(tdir-1)%4;
  977.         else return false; end
  978.         xt.wasTurning=0;
  979.         return true;
  980.     end
  981.     --Orient using torches or ladders. WILL TRY DIGGING BLOCKS
  982.     --Signs, levers and buttons cant be used, they arent placed properly from above
  983.     --XT will learn from its mistakes, and save a table of blocks that cant be placed or torches may be placed
  984.     xt.addValue("cantOrientOn",{
  985.         ["minecraft:glass"]={[0]=true},
  986.         ["ComputerCraft:CC-Peripheral"]={[1]=true},
  987.     });
  988.     function xt.canOrientOn(tab)
  989.         if not tab then return false; end
  990.         if xt.cantOrientOn[tab.name] then
  991.             return not xt.cantOrientOn[tab.name][tab.metadata or tab.damage];
  992.         else return true; end
  993.     end
  994.     function xt.setCantOrientOn(tab)
  995.         if not xt.cantOrientOn[tab.name] then xt.cantOrientOn[tab.name]={}; end
  996.         xt.cantOrientOn[tab.name][tab.metadata or tab.damage]=true;
  997.         xt.save("cantOrientOn");
  998.     end
  999.     function xt.orientDigging()
  1000.         --Search for orienting items
  1001.         local lastS=xt.s;
  1002.         local bslot=false;
  1003.         for i=1,16 do
  1004.             local tab=xt.getItemDetail(i);
  1005.             if tab then
  1006.                 if tab.name=="minecraft:torch" or tab.name=="minecraft:redstone_torch" or tab.name=="minecraft:ladder" then
  1007.                     bslot=i;
  1008.                     break;
  1009.                 end
  1010.             end
  1011.         end
  1012.         --And if we found them, setup the place so that placing the torch will only allow it to face in 1 direction
  1013.         if bslot then
  1014.             local lastF=xt.f;
  1015.             --Search for blocks already placed
  1016.             local foundBlock=false;
  1017.             for i=1,4 do
  1018.                 local tab=xt.inspect();
  1019.                 if tab then
  1020.                     if xt.canOrientOn(tab) then
  1021.                         foundBlock=tab;
  1022.                         break;
  1023.                     else
  1024.                         if not xt.dig() then
  1025.                             xt.face(lastF);
  1026.                             return false,"Found undiggable block";
  1027.                         end
  1028.                     end
  1029.                 end
  1030.                 xt.right();
  1031.             end
  1032.             xt.checkForcemove("justdig",0);
  1033.             xt.pushForcemove("justdig",xt.forceDig);
  1034.             function finish()
  1035.                 xt.popForcemove("justdig");
  1036.                 xt.sel(lastS);
  1037.             end
  1038.             function tryBlock()
  1039.                 xt.fup();
  1040.                 xt.sel(bslot);
  1041.                 if xt.placeDn() then return true;
  1042.                 else
  1043.                     xt.fdn();
  1044.                     return false;
  1045.                 end
  1046.             end
  1047.             if foundBlock then
  1048.                 --Remove all other blocks
  1049.                 for i=1,3 do
  1050.                     xt.right();
  1051.                     if not xt.dig() then
  1052.                         if xt.detect() then
  1053.                             xt.face(lastF);
  1054.                             finish();
  1055.                             return false,"Found undiggable block";
  1056.                         end
  1057.                     end
  1058.                 end
  1059.                 xt.right();
  1060.                 if not xt.digDn() and xt.detectDn() then
  1061.                     xt.face(lastF);
  1062.                     finish();
  1063.                     return
  1064.                 end
  1065.                 --Try the found block
  1066.                 if tryBlock() then
  1067.                     local nowF=xt.f;
  1068.                     if xt.orientTorch(xt.inspectDn(),"back") then
  1069.                         xt.fdn();
  1070.                         xt.quickTurn(lastF-nowF);
  1071.                         finish();
  1072.                         return true;
  1073.                     end
  1074.                 else
  1075.                     xt.setCantOrientOn(foundBlock);
  1076.                 end
  1077.             end
  1078.             --If the already-placed blocks failed, try the blocks in inventory
  1079.             for i=1,16 do
  1080.                 if i~=bslot and xt.getItemCount(i)~=0 then
  1081.                     local tab=xt.getItemDetail(i);
  1082.                     if xt.canOrientOn(tab) then
  1083.                         xt.dig();
  1084.                         xt.sel(i);
  1085.                         if xt.place() then
  1086.                             if not xt.digDn() and xt.detectDn() then
  1087.                                 xt.dig();
  1088.                                 xt.face(lastF);
  1089.                                 finish();
  1090.                                 return false,"Found undiggable block";
  1091.                             end
  1092.                             if tryBlock() then
  1093.                                 local nowF=xt.f;
  1094.                                 if xt.orientTorch(xt.inspectDn(),"back") then
  1095.                                     xt.fdn();
  1096.                                     xt.sel(i);
  1097.                                     xt.dig();
  1098.                                     xt.quickTurn(lastF-nowF);
  1099.                                     finish();
  1100.                                     return true;
  1101.                                 end
  1102.                             else
  1103.                                 xt.setCantOrientOn(tab);
  1104.                             end
  1105.                             xt.sel(i);
  1106.                             xt.dig();
  1107.                         else
  1108.                             xt.setCantOrientOn(tab);
  1109.                         end
  1110.                     end
  1111.                 end
  1112.             end
  1113.             finish();
  1114.             return false,"Could not place orienting item";
  1115.         else return false,"Could not find orienting item"; end
  1116.     end
  1117.    
  1118.     --Misc functions
  1119.     function xt.refuel(count,...)
  1120.         local ok,ret;
  1121.         if count then ok,ret=xt.native.refuel(count);
  1122.         else ok,ret=xt.native.refuel(); end
  1123.         if ok then
  1124.             for n,h in xt.peekAllRefuel() do
  1125.                 h(...);
  1126.             end
  1127.         end
  1128.         return ok,ret;
  1129.     end
  1130.     function xt.getFuel()
  1131.         if xt.fuelUpdated then return xt.fuelUpdated;
  1132.         else return xt.getFuelLevel(); end
  1133.     end
  1134.     function xt.getFuelLevel()
  1135.         xt.fuelUpdated=xt.native.getFuelLevel();
  1136.         return xt.fuelUpdated;
  1137.     end
  1138.     function xt.getCurSlot()
  1139.         xt.s=xt.native.getSelectedSlot();
  1140.         return xt.s;
  1141.     end
  1142.     function xt.sel(s)
  1143.         xt.native.select(s);
  1144.         xt.s=s;
  1145.         return true;
  1146.     end
  1147.     function xt.restoreTurtle()
  1148.         if type(turtle.native)~="table" then return false; end
  1149.         for k,v in pairs(turtle.native) do
  1150.             turtle[k]=v;
  1151.         end
  1152.         turtle.xt_replaced=nil;
  1153.         return true;
  1154.     end
  1155.     function xt.unloadXT()
  1156.         xt.restoreTurtle();
  1157.         _G.xt=nil;
  1158.         return "Bye Bye";
  1159.     end
  1160.     function xt.inspectBase(ifunc)
  1161.         local ok,tab=ifunc();
  1162.         if ok then
  1163.             return tab;
  1164.         else
  1165.             return false,tab;
  1166.         end
  1167.     end
  1168.     function xt.inspect() return xt.inspectBase(xt.native.inspect); end
  1169.     function xt.inspectDn() return xt.inspectBase(xt.native.inspectDown); end
  1170.     function xt.inspectUp() return xt.inspectBase(xt.native.inspectUp); end
  1171.     function xt.addDir(name)
  1172.         if type(name)~="string" then error("name must be a string",2); end
  1173.         local func=xt[name];
  1174.         if type(func)~="function" then error("No "..name.."() function in XT api",2); end
  1175.         local funcUp=xt[name.."Up"];
  1176.         if type(funcUp)~="function" then error("No "..name.."Up() function in XT api",2); end
  1177.         local funcDn=xt[name.."Dn"];
  1178.         if type(funcDn)~="function" then error("No "..name.."Dn() function in XT api",2); end
  1179.         xt[name.."Dir"]=function(dir,...)
  1180.             if dir=="fw" then return func(...);
  1181.             elseif dir=="up" then return funcUp(...);
  1182.             elseif dir=="dn" then return funcDn(...);
  1183.             elseif dir=="bk" then
  1184.                 xt.right(2);
  1185.                 local ok=func(...);
  1186.                 xt.right(2);
  1187.                 return ok;
  1188.             end
  1189.         end
  1190.     end
  1191.    
  1192.     --Check if previous xt replaced turtle
  1193.     if turtle.xt_replaced then xt.restoreTurtle(); end
  1194.     --Copy any missing turtle functions
  1195.     for k,v in pairs(turtle) do
  1196.         if k=="forward" then xt.forward=xt.fw;
  1197.         elseif k=="back" then xt.back=xt.bk;
  1198.         elseif k=="up" then
  1199.         elseif k=="down" then xt.down=xt.dn;
  1200.         elseif k=="turnLeft" then xt.turnLeft=xt.left;
  1201.         elseif k=="turnRight" then xt.turnRight=xt.right;
  1202.         elseif k=="select" then xt.select=xt.sel;
  1203.         elseif k=="inspect" then
  1204.         elseif k=="inspectUp" then
  1205.         elseif k=="inspectDown" then xt.inspectDown=xt.inspectDn;
  1206.         elseif k=="attack" then xt.attack=v;xt.atk=v;xt.attackDir=xt.atkDir;
  1207.         elseif k=="attackUp" then xt.attackUp=v;xt.atkUp=v;
  1208.         elseif k=="attackDown" then xt.attackDown=v;xt.atkDn=v;xt.attackDn=v;
  1209.         elseif k=="digDown" then xt.digDown=v;xt.digDn=v;
  1210.         elseif k=="placeDown" then xt.placeDown=v;xt.placeDn=v;
  1211.         elseif k=="detectDown" then xt.detectDown=v;xt.detectDn=v;
  1212.         elseif k=="compareDown" then xt.compareDown=v;xt.compareDn=v;
  1213.         elseif k=="dropDown" then xt.dropDown=v;xt.dropDn=v;
  1214.         elseif k=="suckDown" then xt.suckDown=v;xt.suckDn=v;
  1215.         elseif k=="refuel" then
  1216.         elseif k=="getFuelLevel" then
  1217.         elseif k=="getSelectedSlot" then xt.getSelectedSlot=xt.getCurSlot;
  1218.         else xt[k]=v; end
  1219.     end
  1220.     --Add ***Dir functions
  1221.     xt.go=xt.fw;
  1222.     xt.goUp=xt.up;
  1223.     xt.goDn=xt.dn;
  1224.     xt.fgo=xt.ffw;
  1225.     xt.fgoUp=xt.fup;
  1226.     xt.fgoDn=xt.fdn;
  1227.     xt.addDir("go");
  1228.     xt.addDir("fgo");
  1229.     xt.addDir("atk");
  1230.     xt.addDir("attack");
  1231.     xt.addDir("dig");
  1232.     xt.addDir("place");
  1233.     xt.addDir("detect");
  1234.     xt.addDir("inspect");
  1235.     xt.addDir("compare");
  1236.     xt.addDir("drop");
  1237.     xt.addDir("suck");
  1238.     xt.forceDig=xt.digDir;
  1239.     xt.forceAtk=xt.atkDir;
  1240.     xt.forceAttack=xt.attackDir;
  1241.     --Replace turtle functions
  1242.     turtle.forward=xt.fw;
  1243.     turtle.back=xt.bk;
  1244.     turtle.up=xt.up;
  1245.     turtle.down=xt.dn;
  1246.     turtle.turnLeft=xt.left;
  1247.     turtle.turnRight=xt.right;
  1248.     turtle.refuel=xt.refuel;
  1249.     turtle.getFuelLevel=xt.getFuelLevel;
  1250.     turtle.select=xt.sel;
  1251.     turtle.xt_replaced=true;
  1252.    
  1253.     xt.getCurSlot();    --Set xt.s
  1254.    
  1255.     --Position error correction
  1256.     function xt.shouldReorient()
  1257.         if xt.wasTurning==nil then error("Orientation checking is not enabled",2); end
  1258.         return xt.wasTurning>0;
  1259.     end
  1260.     function xt.shouldRelocate()
  1261.         return not not xt.moveData[1];  --Returns true or false only (so relocation isnt manually, and wrongly, done)
  1262.     end
  1263.     function xt.correctPosition()
  1264.         if xt.shouldRelocate() then
  1265.             local b=xt.detect();    --Make sure previous move finishes (and gather data!)
  1266.             local fuel=xt.getFuelLevel();
  1267.             if fuel=="unlimited" then
  1268.                 if not b then xt.doMove(xt.moveData[1],1); end  --Try our best
  1269.             else
  1270.                 if xt.moveData[2]-fuel==1 then
  1271.                     xt.doMove(xt.moveData[1],1);
  1272.                 end
  1273.             end
  1274.             xt.moveData[1]=false;
  1275.             xt.save("moveData");
  1276.         end
  1277.     end
  1278.     xt.correctPosition();
  1279. end
  1280.  
  1281. _G.xt=xt;       --Export xt api to global environment
Advertisement
Add Comment
Please, Sign In to add comment