SHOW:
|
|
- or go back to the newest paste.
| 1 | tArgs = {...}
| |
| 2 | ||
| 3 | if OneOS then | |
| 4 | --running under OneOS | |
| 5 | OneOS.ToolBarColour = colours.white | |
| 6 | OneOS.ToolBarTextColour = colours.grey | |
| 7 | end | |
| 8 | ||
| 9 | local _w, _h = term.getSize() | |
| 10 | ||
| 11 | local round = function(num, idp) | |
| 12 | local mult = 10^(idp or 0) | |
| 13 | return math.floor(num * mult + 0.5) / mult | |
| 14 | end | |
| 15 | ||
| 16 | InterfaceElements = {}
| |
| 17 | ||
| 18 | Drawing = {
| |
| 19 | ||
| 20 | Screen = {
| |
| 21 | Width = _w, | |
| 22 | Height = _h | |
| 23 | }, | |
| 24 | ||
| 25 | DrawCharacters = function (x, y, characters, textColour,bgColour) | |
| 26 | Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour) | |
| 27 | end, | |
| 28 | ||
| 29 | DrawBlankArea = function (x, y, w, h, colour) | |
| 30 | Drawing.DrawArea (x, y, w, h, " ", 1, colour) | |
| 31 | end, | |
| 32 | ||
| 33 | DrawArea = function (x, y, w, h, character, textColour, bgColour) | |
| 34 | --width must be greater than 1, other wise we get a stack overflow | |
| 35 | if w < 0 then | |
| 36 | w = w * -1 | |
| 37 | elseif w == 0 then | |
| 38 | w = 1 | |
| 39 | end | |
| 40 | ||
| 41 | for ix = 1, w do | |
| 42 | local currX = x + ix - 1 | |
| 43 | for iy = 1, h do | |
| 44 | local currY = y + iy - 1 | |
| 45 | Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour) | |
| 46 | end | |
| 47 | end | |
| 48 | end, | |
| 49 | ||
| 50 | DrawImage = function(_x,_y,tImage, w, h) | |
| 51 | if tImage then | |
| 52 | for y = 1, h do | |
| 53 | if not tImage[y] then | |
| 54 | break | |
| 55 | end | |
| 56 | for x = 1, w do | |
| 57 | if not tImage[y][x] then | |
| 58 | break | |
| 59 | end | |
| 60 | local bgColour = tImage[y][x] | |
| 61 | local textColour = tImage.textcol[y][x] or colours.white | |
| 62 | local char = tImage.text[y][x] | |
| 63 | Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour) | |
| 64 | end | |
| 65 | end | |
| 66 | elseif w and h then | |
| 67 | Drawing.DrawBlankArea(x, y, w, h, colours.green) | |
| 68 | end | |
| 69 | end, | |
| 70 | --using .nft | |
| 71 | LoadImage = function(path) | |
| 72 | local image = {
| |
| 73 | text = {},
| |
| 74 | textcol = {}
| |
| 75 | } | |
| 76 | local fs = fs | |
| 77 | if OneOS then | |
| 78 | fs = OneOS.FS | |
| 79 | end | |
| 80 | if fs.exists(path) then | |
| 81 | local _open = io.open | |
| 82 | if OneOS then | |
| 83 | _open = OneOS.IO.open | |
| 84 | end | |
| 85 | local file = _open(path, "r") | |
| 86 | local sLine = file:read() | |
| 87 | local num = 1 | |
| 88 | while sLine do | |
| 89 | table.insert(image, num, {})
| |
| 90 | table.insert(image.text, num, {})
| |
| 91 | table.insert(image.textcol, num, {})
| |
| 92 | ||
| 93 | --As we're no longer 1-1, we keep track of what index to write to | |
| 94 | local writeIndex = 1 | |
| 95 | --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour | |
| 96 | local bgNext, fgNext = false, false | |
| 97 | --The current background and foreground colours | |
| 98 | local currBG, currFG = nil,nil | |
| 99 | for i=1,#sLine do | |
| 100 | local nextChar = string.sub(sLine, i, i) | |
| 101 | if nextChar:byte() == 30 then | |
| 102 | bgNext = true | |
| 103 | elseif nextChar:byte() == 31 then | |
| 104 | fgNext = true | |
| 105 | elseif bgNext then | |
| 106 | currBG = Drawing.GetColour(nextChar) | |
| 107 | bgNext = false | |
| 108 | elseif fgNext then | |
| 109 | currFG = Drawing.GetColour(nextChar) | |
| 110 | fgNext = false | |
| 111 | else | |
| 112 | if nextChar ~= " " and currFG == nil then | |
| 113 | currFG = colours.white | |
| 114 | end | |
| 115 | image[num][writeIndex] = currBG | |
| 116 | image.textcol[num][writeIndex] = currFG | |
| 117 | image.text[num][writeIndex] = nextChar | |
| 118 | writeIndex = writeIndex + 1 | |
| 119 | end | |
| 120 | end | |
| 121 | num = num+1 | |
| 122 | sLine = file:read() | |
| 123 | end | |
| 124 | file:close() | |
| 125 | end | |
| 126 | return image | |
| 127 | end, | |
| 128 | ||
| 129 | DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour) | |
| 130 | w = w or Drawing.Screen.Width | |
| 131 | h = h or Drawing.Screen.Height | |
| 132 | x = x or 0 | |
| 133 | y = y or 0 | |
| 134 | x = math.ceil((w - #characters) / 2) + x | |
| 135 | y = math.floor(h / 2) + y | |
| 136 | ||
| 137 | Drawing.DrawCharacters(x, y, characters, textColour, bgColour) | |
| 138 | end, | |
| 139 | ||
| 140 | GetColour = function(hex) | |
| 141 | if hex == ' ' then | |
| 142 | return colours.transparent | |
| 143 | end | |
| 144 | local value = tonumber(hex, 16) | |
| 145 | if not value then return nil end | |
| 146 | value = math.pow(2,value) | |
| 147 | return value | |
| 148 | end, | |
| 149 | ||
| 150 | Clear = function (_colour) | |
| 151 | _colour = _colour or colours.black | |
| 152 | Drawing.ClearBuffer() | |
| 153 | Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour) | |
| 154 | end, | |
| 155 | ||
| 156 | Buffer = {},
| |
| 157 | BackBuffer = {},
| |
| 158 | ||
| 159 | DrawBuffer = function() | |
| 160 | for y,row in pairs(Drawing.Buffer) do | |
| 161 | for x,pixel in pairs(row) do | |
| 162 | local shouldDraw = true | |
| 163 | local hasBackBuffer = true | |
| 164 | if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then | |
| 165 | hasBackBuffer = false | |
| 166 | end | |
| 167 | if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then | |
| 168 | shouldDraw = false | |
| 169 | end | |
| 170 | if shouldDraw then | |
| 171 | term.setBackgroundColour(pixel[3]) | |
| 172 | term.setTextColour(pixel[2]) | |
| 173 | term.setCursorPos(x, y) | |
| 174 | term.write(pixel[1]) | |
| 175 | end | |
| 176 | end | |
| 177 | end | |
| 178 | Drawing.BackBuffer = Drawing.Buffer | |
| 179 | Drawing.Buffer = {}
| |
| 180 | term.setCursorPos(1,1) | |
| 181 | end, | |
| 182 | ||
| 183 | ClearBuffer = function() | |
| 184 | Drawing.Buffer = {}
| |
| 185 | end, | |
| 186 | ||
| 187 | WriteStringToBuffer = function (x, y, characters, textColour,bgColour) | |
| 188 | for i = 1, #characters do | |
| 189 | local character = characters:sub(i,i) | |
| 190 | Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour) | |
| 191 | end | |
| 192 | end, | |
| 193 | ||
| 194 | WriteToBuffer = function(x, y, character, textColour,bgColour) | |
| 195 | x = round(x) | |
| 196 | y = round(y) | |
| 197 | if bgColour == colours.transparent then | |
| 198 | Drawing.Buffer[y] = Drawing.Buffer[y] or {}
| |
| 199 | Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
| |
| 200 | Drawing.Buffer[y][x][1] = character | |
| 201 | Drawing.Buffer[y][x][2] = textColour | |
| 202 | else | |
| 203 | Drawing.Buffer[y] = Drawing.Buffer[y] or {}
| |
| 204 | Drawing.Buffer[y][x] = {character, textColour, bgColour}
| |
| 205 | end | |
| 206 | end, | |
| 207 | } | |
| 208 | ||
| 209 | Current = {
| |
| 210 | Document = nil, | |
| 211 | TextInput = nil, | |
| 212 | CursorPos = {1,1},
| |
| 213 | CursorColour = colours.black, | |
| 214 | Selection = {8, 36},
| |
| 215 | Window = nil, | |
| 216 | HeaderText = '', | |
| 217 | StatusText = '', | |
| 218 | StatusColour = colours.grey, | |
| 219 | StatusScreen = true, | |
| 220 | ButtonOne = nil, | |
| 221 | ButtonTwo = nil, | |
| 222 | Locked = false, | |
| 223 | Page = '', | |
| 224 | PageControls = {}
| |
| 225 | } | |
| 226 | ||
| 227 | isRunning = true | |
| 228 | ||
| 229 | Events = {}
| |
| 230 | ||
| 231 | Button = {
| |
| 232 | X = 1, | |
| 233 | Y = 1, | |
| 234 | Width = 0, | |
| 235 | Height = 0, | |
| 236 | BackgroundColour = colours.lightGrey, | |
| 237 | TextColour = colours.white, | |
| 238 | ActiveBackgroundColour = colours.lightGrey, | |
| 239 | Text = "", | |
| 240 | Parent = nil, | |
| 241 | _Click = nil, | |
| 242 | Toggle = nil, | |
| 243 | ||
| 244 | AbsolutePosition = function(self) | |
| 245 | return self.Parent:AbsolutePosition() | |
| 246 | end, | |
| 247 | ||
| 248 | Draw = function(self) | |
| 249 | local bg = self.BackgroundColour | |
| 250 | local tc = self.TextColour | |
| 251 | if type(bg) == 'function' then | |
| 252 | bg = bg() | |
| 253 | end | |
| 254 | ||
| 255 | if self.Toggle then | |
| 256 | tc = colours.white | |
| 257 | bg = self.ActiveBackgroundColour | |
| 258 | end | |
| 259 | ||
| 260 | local pos = GetAbsolutePosition(self) | |
| 261 | Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg) | |
| 262 | Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg) | |
| 263 | end, | |
| 264 | ||
| 265 | Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour) | |
| 266 | local new = {} -- the new instance
| |
| 267 | setmetatable( new, {__index = self} )
| |
| 268 | height = height or 1 | |
| 269 | new.Width = width or #text + 2 | |
| 270 | new.Height = height | |
| 271 | new.Y = y | |
| 272 | new.X = x | |
| 273 | new.Text = text or "" | |
| 274 | new.BackgroundColour = backgroundColour or colours.lightGrey | |
| 275 | new.TextColour = textColour or colours.white | |
| 276 | new.ActiveBackgroundColour = activeBackgroundColour or colours.lightBlue | |
| 277 | new.Parent = parent | |
| 278 | new._Click = click | |
| 279 | new.Toggle = toggle | |
| 280 | return new | |
| 281 | end, | |
| 282 | ||
| 283 | Click = function(self, side, x, y) | |
| 284 | if self._Click then | |
| 285 | if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then | |
| 286 | self.Toggle = not self.Toggle | |
| 287 | Draw() | |
| 288 | end | |
| 289 | return true | |
| 290 | else | |
| 291 | return false | |
| 292 | end | |
| 293 | end | |
| 294 | } | |
| 295 | ||
| 296 | Label = {
| |
| 297 | X = 1, | |
| 298 | Y = 1, | |
| 299 | Width = 0, | |
| 300 | Height = 0, | |
| 301 | BackgroundColour = colours.lightGrey, | |
| 302 | TextColour = colours.white, | |
| 303 | Text = "", | |
| 304 | Parent = nil, | |
| 305 | ||
| 306 | AbsolutePosition = function(self) | |
| 307 | return self.Parent:AbsolutePosition() | |
| 308 | end, | |
| 309 | ||
| 310 | Draw = function(self) | |
| 311 | local bg = self.BackgroundColour | |
| 312 | local tc = self.TextColour | |
| 313 | ||
| 314 | if self.Toggle then | |
| 315 | tc = UIColours.MenuBarActive | |
| 316 | bg = self.ActiveBackgroundColour | |
| 317 | end | |
| 318 | ||
| 319 | local pos = GetAbsolutePosition(self) | |
| 320 | Drawing.DrawCharacters(pos.X, pos.Y, self.Text, self.TextColour, self.BackgroundColour) | |
| 321 | end, | |
| 322 | ||
| 323 | Initialise = function(self, x, y, text, textColour, backgroundColour, parent) | |
| 324 | local new = {} -- the new instance
| |
| 325 | setmetatable( new, {__index = self} )
| |
| 326 | height = height or 1 | |
| 327 | new.Width = width or #text + 2 | |
| 328 | new.Height = height | |
| 329 | new.Y = y | |
| 330 | new.X = x | |
| 331 | new.Text = text or "" | |
| 332 | new.BackgroundColour = backgroundColour or colours.white | |
| 333 | new.TextColour = textColour or colours.black | |
| 334 | new.Parent = parent | |
| 335 | return new | |
| 336 | end, | |
| 337 | ||
| 338 | Click = function(self, side, x, y) | |
| 339 | return false | |
| 340 | end | |
| 341 | } | |
| 342 | ||
| 343 | TextBox = {
| |
| 344 | X = 1, | |
| 345 | Y = 1, | |
| 346 | Width = 0, | |
| 347 | Height = 0, | |
| 348 | BackgroundColour = colours.lightGrey, | |
| 349 | TextColour = colours.black, | |
| 350 | Parent = nil, | |
| 351 | TextInput = nil, | |
| 352 | Placeholder = '', | |
| 353 | ||
| 354 | AbsolutePosition = function(self) | |
| 355 | return self.Parent:AbsolutePosition() | |
| 356 | end, | |
| 357 | ||
| 358 | Draw = function(self) | |
| 359 | local pos = GetAbsolutePosition(self) | |
| 360 | Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour) | |
| 361 | local text = self.TextInput.Value | |
| 362 | if #tostring(text) > (self.Width - 2) then | |
| 363 | text = text:sub(#text-(self.Width - 3)) | |
| 364 | if Current.TextInput == self.TextInput then | |
| 365 | Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
| |
| 366 | end | |
| 367 | else | |
| 368 | if Current.TextInput == self.TextInput then | |
| 369 | Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
| |
| 370 | end | |
| 371 | end | |
| 372 | ||
| 373 | if #tostring(text) == 0 then | |
| 374 | Drawing.DrawCharacters(pos.X + 1, pos.Y, self.Placeholder, colours.lightGrey, self.BackgroundColour) | |
| 375 | else | |
| 376 | Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour) | |
| 377 | end | |
| 378 | ||
| 379 | term.setCursorBlink(true) | |
| 380 | ||
| 381 | Current.CursorColour = self.TextColour | |
| 382 | end, | |
| 383 | ||
| 384 | Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical) | |
| 385 | local new = {} -- the new instance
| |
| 386 | setmetatable( new, {__index = self} )
| |
| 387 | height = height or 1 | |
| 388 | new.Width = width or #text + 2 | |
| 389 | new.Height = height | |
| 390 | new.Y = y | |
| 391 | new.X = x | |
| 392 | new.TextInput = TextInput:Initialise(text or '', function(key) | |
| 393 | if done then | |
| 394 | done(key) | |
| 395 | end | |
| 396 | Draw() | |
| 397 | end, numerical) | |
| 398 | new.BackgroundColour = backgroundColour or colours.lightGrey | |
| 399 | new.TextColour = textColour or colours.black | |
| 400 | new.Parent = parent | |
| 401 | return new | |
| 402 | end, | |
| 403 | ||
| 404 | Click = function(self, side, x, y) | |
| 405 | Current.Input = self.TextInput | |
| 406 | self:Draw() | |
| 407 | end | |
| 408 | } | |
| 409 | ||
| 410 | TextInput = {
| |
| 411 | Value = "", | |
| 412 | Change = nil, | |
| 413 | CursorPos = nil, | |
| 414 | Numerical = false, | |
| 415 | IsDocument = nil, | |
| 416 | ||
| 417 | Initialise = function(self, value, change, numerical, isDocument) | |
| 418 | local new = {} -- the new instance
| |
| 419 | setmetatable( new, {__index = self} )
| |
| 420 | new.Value = tostring(value) | |
| 421 | new.Change = change | |
| 422 | new.CursorPos = #tostring(value) | |
| 423 | new.Numerical = numerical | |
| 424 | new.IsDocument = isDocument or false | |
| 425 | return new | |
| 426 | end, | |
| 427 | ||
| 428 | Insert = function(self, str) | |
| 429 | if self.Numerical then | |
| 430 | str = tostring(tonumber(str)) | |
| 431 | end | |
| 432 | ||
| 433 | local selection = OrderSelection() | |
| 434 | ||
| 435 | if self.IsDocument and selection then | |
| 436 | self.Value = string.sub(self.Value, 1, selection[1]-1) .. str .. string.sub( self.Value, selection[2]+2) | |
| 437 | self.CursorPos = selection[1] | |
| 438 | Current.Selection = nil | |
| 439 | else | |
| 440 | local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','') | |
| 441 | ||
| 442 | self.Value = string.sub(self.Value, 1, self.CursorPos + newLineAdjust) .. str .. string.sub( self.Value, self.CursorPos + 1 + newLineAdjust) | |
| 443 | self.CursorPos = self.CursorPos + 1 | |
| 444 | end | |
| 445 | ||
| 446 | self.Change(key) | |
| 447 | end, | |
| 448 | ||
| 449 | Extract = function(self, remove) | |
| 450 | local selection = OrderSelection() | |
| 451 | if self.IsDocument and selection then | |
| 452 | local _, newLineAdjust = string.gsub(self.Value:sub(selection[1], selection[2]), '\n','') | |
| 453 | local str = string.sub(self.Value, selection[1], selection[2]+1+newLineAdjust) | |
| 454 | if remove then | |
| 455 | self.Value = string.sub(self.Value, 1, selection[1]-1) .. string.sub( self.Value, selection[2]+2+newLineAdjust) | |
| 456 | self.CursorPos = selection[1] - 1 | |
| 457 | Current.Selection = nil | |
| 458 | end | |
| 459 | return str | |
| 460 | end | |
| 461 | end, | |
| 462 | ||
| 463 | Char = function(self, char) | |
| 464 | if char == 'nil' then | |
| 465 | return | |
| 466 | end | |
| 467 | self:Insert(char) | |
| 468 | end, | |
| 469 | ||
| 470 | Key = function(self, key) | |
| 471 | if key == keys.enter then | |
| 472 | if self.IsDocument then | |
| 473 | self.Value = string.sub(self.Value, 1, self.CursorPos ) .. '\n' .. string.sub( self.Value, self.CursorPos + 1 ) | |
| 474 | self.CursorPos = self.CursorPos + 1 | |
| 475 | end | |
| 476 | self.Change(key) | |
| 477 | elseif key == keys.left then | |
| 478 | -- Left | |
| 479 | if self.CursorPos > 0 then | |
| 480 | local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos)) | |
| 481 | self.CursorPos = self.CursorPos - 1 - colShift | |
| 482 | self.Change(key) | |
| 483 | end | |
| 484 | ||
| 485 | elseif key == keys.right then | |
| 486 | -- Right | |
| 487 | if self.CursorPos < string.len(self.Value) then | |
| 488 | local colShift = FindColours(string.sub( self.Value, self.CursorPos+1, self.CursorPos+1)) | |
| 489 | self.CursorPos = self.CursorPos + 1 + colShift | |
| 490 | self.Change(key) | |
| 491 | end | |
| 492 | ||
| 493 | elseif key == keys.backspace then | |
| 494 | -- Backspace | |
| 495 | if self.IsDocument and Current.Selection then | |
| 496 | self:Extract(true) | |
| 497 | self.Change(key) | |
| 498 | elseif self.CursorPos > 0 then | |
| 499 | local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos)) | |
| 500 | local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','') | |
| 501 | ||
| 502 | self.Value = string.sub( self.Value, 1, self.CursorPos - 1 - colShift + newLineAdjust) .. string.sub( self.Value, self.CursorPos + 1 - colShift + newLineAdjust) | |
| 503 | self.CursorPos = self.CursorPos - 1 - colShift | |
| 504 | self.Change(key) | |
| 505 | end | |
| 506 | elseif key == keys.home then | |
| 507 | -- Home | |
| 508 | self.CursorPos = 0 | |
| 509 | self.Change(key) | |
| 510 | elseif key == keys.delete then | |
| 511 | if self.IsDocument and Current.Selection then | |
| 512 | self:Extract(true) | |
| 513 | self.Change(key) | |
| 514 | elseif self.CursorPos < string.len(self.Value) then | |
| 515 | self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 ) | |
| 516 | self.Change(key) | |
| 517 | end | |
| 518 | elseif key == keys["end"] then | |
| 519 | -- End | |
| 520 | self.CursorPos = string.len(self.Value) | |
| 521 | self.Change(key) | |
| 522 | elseif key == keys.up and self.IsDocument then | |
| 523 | -- Up | |
| 524 | if Current.Document.CursorPos then | |
| 525 | local page = Current.Document.Pages[Current.Document.CursorPos.Page] | |
| 526 | self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY - 1 + Current.Document.ScrollBar.Scroll, true) | |
| 527 | self.Change(key) | |
| 528 | end | |
| 529 | elseif key == keys.down and self.IsDocument then | |
| 530 | -- Down | |
| 531 | if Current.Document.CursorPos then | |
| 532 | local page = Current.Document.Pages[Current.Document.CursorPos.Page] | |
| 533 | self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY + 1 + Current.Document.ScrollBar.Scroll, true) | |
| 534 | self.Change(key) | |
| 535 | end | |
| 536 | end | |
| 537 | end | |
| 538 | } | |
| 539 | ||
| 540 | local Capitalise = function(str) | |
| 541 | return str:sub(1, 1):upper() .. str:sub(2, -1) | |
| 542 | end | |
| 543 | ||
| 544 | ||
| 545 | local getNames = peripheral.getNames or function() | |
| 546 | local tResults = {}
| |
| 547 | for n,sSide in ipairs( rs.getSides() ) do | |
| 548 | if peripheral.isPresent( sSide ) then | |
| 549 | table.insert( tResults, sSide ) | |
| 550 | local isWireless = false | |
| 551 | if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then | |
| 552 | isWireless = true | |
| 553 | end | |
| 554 | if peripheral.getType( sSide ) == "modem" and not isWireless then | |
| 555 | local tRemote = peripheral.call( sSide, "getNamesRemote" ) | |
| 556 | for n,sName in ipairs( tRemote ) do | |
| 557 | table.insert( tResults, sName ) | |
| 558 | end | |
| 559 | end | |
| 560 | end | |
| 561 | end | |
| 562 | return tResults | |
| 563 | end | |
| 564 | ||
| 565 | Peripheral = {
| |
| 566 | GetPeripheral = function(_type) | |
| 567 | for i, p in ipairs(Peripheral.GetPeripherals()) do | |
| 568 | if p.Type == _type then | |
| 569 | return p | |
| 570 | end | |
| 571 | end | |
| 572 | end, | |
| 573 | ||
| 574 | Call = function(type, ...) | |
| 575 | local tArgs = {...}
| |
| 576 | local p = Peripheral.GetPeripheral(type) | |
| 577 | peripheral.call(p.Side, unpack(tArgs)) | |
| 578 | end, | |
| 579 | ||
| 580 | GetPeripherals = function(filterType) | |
| 581 | local peripherals = {}
| |
| 582 | for i, side in ipairs(getNames()) do | |
| 583 | local name = peripheral.getType(side):gsub("^%l", string.upper)
| |
| 584 | local code = string.upper(side:sub(1,1)) | |
| 585 | if side:find('_') then
| |
| 586 | code = side:sub(side:find('_')+1)
| |
| 587 | end | |
| 588 | ||
| 589 | local dupe = false | |
| 590 | for i, v in ipairs(peripherals) do | |
| 591 | if v[1] == name .. ' ' .. code then | |
| 592 | dupe = true | |
| 593 | end | |
| 594 | end | |
| 595 | ||
| 596 | if not dupe then | |
| 597 | local _type = peripheral.getType(side) | |
| 598 | local isWireless = false | |
| 599 | if _type == 'modem' then | |
| 600 | if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then | |
| 601 | isWireless = true | |
| 602 | end | |
| 603 | if isWireless then | |
| 604 | _type = 'wireless_modem' | |
| 605 | name = 'W '..name | |
| 606 | end | |
| 607 | end | |
| 608 | if not filterType or _type == filterType then | |
| 609 | table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless})
| |
| 610 | end | |
| 611 | end | |
| 612 | end | |
| 613 | return peripherals | |
| 614 | end, | |
| 615 | ||
| 616 | PresentNamed = function(name) | |
| 617 | return peripheral.isPresent(name) | |
| 618 | end, | |
| 619 | ||
| 620 | CallType = function(type, ...) | |
| 621 | local tArgs = {...}
| |
| 622 | local p = Peripheral.GetPeripheral(type) | |
| 623 | return peripheral.call(p.Side, unpack(tArgs)) | |
| 624 | end, | |
| 625 | ||
| 626 | CallNamed = function(name, ...) | |
| 627 | local tArgs = {...}
| |
| 628 | return peripheral.call(name, unpack(tArgs)) | |
| 629 | end | |
| 630 | } | |
| 631 | ||
| 632 | Wireless = {
| |
| 633 | Channels = {
| |
| 634 | UltimateDoorlockPing = 4210, | |
| 635 | UltimateDoorlockRequest = 4211, | |
| 636 | UltimateDoorlockRequestReply = 4212, | |
| 637 | }, | |
| 638 | ||
| 639 | isOpen = function(channel) | |
| 640 | return Peripheral.CallType('wireless_modem', 'isOpen', channel)
| |
| 641 | end, | |
| 642 | ||
| 643 | Open = function(channel) | |
| 644 | if not Wireless.isOpen(channel) then | |
| 645 | Peripheral.CallType('wireless_modem', 'open', channel)
| |
| 646 | end | |
| 647 | end, | |
| 648 | ||
| 649 | close = function(channel) | |
| 650 | Peripheral.CallType('wireless_modem', 'close', channel)
| |
| 651 | end, | |
| 652 | ||
| 653 | closeAll = function() | |
| 654 | Peripheral.CallType('wireless_modem', 'closeAll')
| |
| 655 | end, | |
| 656 | ||
| 657 | transmit = function(channel, replyChannel, message) | |
| 658 | Peripheral.CallType('wireless_modem', 'transmit', channel, replyChannel, textutils.serialize(message))
| |
| 659 | end, | |
| 660 | ||
| 661 | Present = function() | |
| 662 | if Peripheral.GetPeripheral('wireless_modem') == nil then
| |
| 663 | return false | |
| 664 | else | |
| 665 | return true | |
| 666 | end | |
| 667 | end, | |
| 668 | ||
| 669 | FormatMessage = function(message, messageID, destinationID) | |
| 670 | return {
| |
| 671 | content = textutils.serialize(message), | |
| 672 | senderID = os.getComputerID(), | |
| 673 | senderName = os.getComputerLabel(), | |
| 674 | channel = channel, | |
| 675 | replyChannel = reply, | |
| 676 | messageID = messageID or math.random(10000), | |
| 677 | destinationID = destinationID | |
| 678 | } | |
| 679 | end, | |
| 680 | ||
| 681 | Timeout = function(func, time) | |
| 682 | time = time or 1 | |
| 683 | parallel.waitForAny(func, function() | |
| 684 | sleep(time) | |
| 685 | --log('Timeout!'..time)
| |
| 686 | end) | |
| 687 | end, | |
| 688 | ||
| 689 | RecieveMessage = function(_channel, messageID, timeout) | |
| 690 | open(_channel) | |
| 691 | local done = false | |
| 692 | local event, side, channel, replyChannel, message = nil | |
| 693 | Timeout(function() | |
| 694 | while not done do | |
| 695 | event, side, channel, replyChannel, message = os.pullEvent('modem_message')
| |
| 696 | if channel ~= _channel then | |
| 697 | event, side, channel, replyChannel, message = nil | |
| 698 | else | |
| 699 | message = textutils.unserialize(message) | |
| 700 | message.content = textutils.unserialize(message.content) | |
| 701 | if messageID and messageID ~= message.messageID or (message.destinationID ~= nil and message.destinationID ~= os.getComputerID()) then | |
| 702 | event, side, channel, replyChannel, message = nil | |
| 703 | else | |
| 704 | done = true | |
| 705 | end | |
| 706 | end | |
| 707 | end | |
| 708 | end, | |
| 709 | timeout) | |
| 710 | return event, side, channel, replyChannel, message | |
| 711 | end, | |
| 712 | ||
| 713 | Initialise = function() | |
| 714 | if Wireless.Present() then | |
| 715 | for i, c in pairs(Wireless.Channels) do | |
| 716 | Wireless.Open(c) | |
| 717 | end | |
| 718 | end | |
| 719 | end, | |
| 720 | ||
| 721 | HandleMessage = function(event, side, channel, replyChannel, message, distance) | |
| 722 | message = textutils.unserialize(message) | |
| 723 | message.content = textutils.unserialize(message.content) | |
| 724 | ||
| 725 | if channel == Wireless.Channels.Ping then | |
| 726 | if message.content == 'Ping!' then | |
| 727 | SendMessage(replyChannel, 'Pong!', nil, message.messageID) | |
| 728 | end | |
| 729 | elseif message.destinationID ~= nil and message.destinationID ~= os.getComputerID() then | |
| 730 | elseif Wireless.Responder then | |
| 731 | Wireless.Responder(event, side, channel, replyChannel, message, distance) | |
| 732 | end | |
| 733 | end, | |
| 734 | ||
| 735 | SendMessage = function(channel, message, reply, messageID, destinationID) | |
| 736 | reply = reply or channel + 1 | |
| 737 | Wireless.Open(channel) | |
| 738 | Wireless.Open(reply) | |
| 739 | local _message = Wireless.FormatMessage(message, messageID, destinationID) | |
| 740 | Wireless.transmit(channel, reply, _message) | |
| 741 | return _message | |
| 742 | end, | |
| 743 | ||
| 744 | Ping = function() | |
| 745 | local message = SendMessage(Channels.Ping, 'Ping!', Channels.PingReply) | |
| 746 | RecieveMessage(Channels.PingReply, message.messageID) | |
| 747 | end | |
| 748 | } | |
| 749 | ||
| 750 | function GetAbsolutePosition(object) | |
| 751 | local obj = object | |
| 752 | local i = 0 | |
| 753 | local x = 1 | |
| 754 | local y = 1 | |
| 755 | while true do | |
| 756 | x = x + obj.X - 1 | |
| 757 | y = y + obj.Y - 1 | |
| 758 | ||
| 759 | if not obj.Parent then | |
| 760 | return {X = x, Y = y}
| |
| 761 | end | |
| 762 | ||
| 763 | obj = obj.Parent | |
| 764 | ||
| 765 | if i > 32 then | |
| 766 | return {X = 1, Y = 1}
| |
| 767 | end | |
| 768 | ||
| 769 | i = i + 1 | |
| 770 | end | |
| 771 | ||
| 772 | end | |
| 773 | ||
| 774 | function Draw() | |
| 775 | Drawing.Clear(colours.white) | |
| 776 | ||
| 777 | if Current.StatusScreen then | |
| 778 | Drawing.DrawCharactersCenter(1, -2, nil, nil, Current.HeaderText, colours.blue, colours.white) | |
| 779 | Drawing.DrawCharactersCenter(1, -1, nil, nil, 'by oeed', colours.lightGrey, colours.white) | |
| 780 | Drawing.DrawCharactersCenter(1, 1, nil, nil, Current.StatusText, Current.StatusColour, colours.white) | |
| 781 | end | |
| 782 | ||
| 783 | if Current.ButtonOne then | |
| 784 | Current.ButtonOne:Draw() | |
| 785 | end | |
| 786 | ||
| 787 | if Current.ButtonTwo then | |
| 788 | Current.ButtonTwo:Draw() | |
| 789 | end | |
| 790 | ||
| 791 | for i, v in ipairs(Current.PageControls) do | |
| 792 | v:Draw() | |
| 793 | end | |
| 794 | ||
| 795 | Drawing.DrawBuffer() | |
| 796 | ||
| 797 | if Current.TextInput and Current.CursorPos and not Current.Menu and not(Current.Window and Current.Document and Current.TextInput == Current.Document.TextInput) and Current.CursorPos[2] > 1 then | |
| 798 | term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2]) | |
| 799 | term.setCursorBlink(true) | |
| 800 | term.setTextColour(Current.CursorColour) | |
| 801 | else | |
| 802 | term.setCursorBlink(false) | |
| 803 | end | |
| 804 | end | |
| 805 | MainDraw = Draw | |
| 806 | ||
| 807 | function GenerateFingerprint() | |
| 808 | local str = "" | |
| 809 | for _ = 1, 256 do | |
| 810 | local char = math.random(32, 126) | |
| 811 | --if char == 96 then char = math.random(32, 95) end | |
| 812 | str = str .. string.char(char) | |
| 813 | end | |
| 814 | return str | |
| 815 | end | |
| 816 | ||
| 817 | function MakeFingerprint() | |
| 818 | local h = fs.open('.fingerprint', 'w')
| |
| 819 | if h then | |
| 820 | h.write(GenerateFingerprint()) | |
| 821 | end | |
| 822 | h.close() | |
| 823 | Current.Fingerprint = str | |
| 824 | end | |
| 825 | ||
| 826 | local drawTimer = nil | |
| 827 | function SetText(header, status, colour, isReset) | |
| 828 | if header then | |
| 829 | Current.HeaderText = header | |
| 830 | end | |
| 831 | if status then | |
| 832 | Current.StatusText = status | |
| 833 | end | |
| 834 | if colour then | |
| 835 | Current.StatusColour = colour | |
| 836 | end | |
| 837 | Draw() | |
| 838 | if not isReset then | |
| 839 | statusResetTimer = os.startTimer(2) | |
| 840 | end | |
| 841 | end | |
| 842 | ||
| 843 | function ResetStatus() | |
| 844 | if pocket then | |
| 845 | if Current.Locked then | |
| 846 | SetText('Ultimate Door Lock', 'Add Wireless Modem to PDA', colours.red, true)
| |
| 847 | else | |
| 848 | SetText('Ultimate Door Lock', 'Ready', colours.grey, true)
| |
| 849 | end | |
| 850 | else | |
| 851 | if Current.Locked then | |
| 852 | SetText('Ultimate Door Lock', ' Attach a Wireless Modem then reboot', colours.red, true)
| |
| 853 | else | |
| 854 | SetText('Ultimate Door Lock', 'Ready', colours.grey, true)
| |
| 855 | end | |
| 856 | end | |
| 857 | end | |
| 858 | ||
| 859 | function ResetPage() | |
| 860 | Wireless.Responder = function()end | |
| 861 | pingTimer = nil | |
| 862 | Current.PageControls = nil | |
| 863 | Current.StatusScreen = false | |
| 864 | Current.ButtonOne = nil | |
| 865 | Current.ButtonTwo = nil | |
| 866 | Current.PageControls = {}
| |
| 867 | CloseDoor() | |
| 868 | end | |
| 869 | ||
| 870 | function PocketInitialise() | |
| 871 | Current.ButtonOne = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, Quit, 'Quit', colours.black) | |
| 872 | if not Wireless.Present() then | |
| 873 | Current.Locked = true | |
| 874 | ResetStatus() | |
| 875 | return | |
| 876 | end | |
| 877 | Wireless.Initialise() | |
| 878 | ResetStatus() | |
| 879 | if fs.exists('.fingerprint') then
| |
| 880 | local h = fs.open('.fingerprint', 'r')
| |
| 881 | if h then | |
| 882 | Current.Fingerprint = h.readAll() | |
| 883 | else | |
| 884 | MakeFingerprint() | |
| 885 | end | |
| 886 | h.close() | |
| 887 | else | |
| 888 | MakeFingerprint() | |
| 889 | end | |
| 890 | ||
| 891 | Wireless.Responder = function(event, side, channel, replyChannel, message, distance) | |
| 892 | if channel == Wireless.Channels.UltimateDoorlockPing then | |
| 893 | Wireless.SendMessage(Wireless.Channels.UltimateDoorlockRequest, Current.Fingerprint, Wireless.Channels.UltimateDoorlockRequestReply, nil, message.senderID) | |
| 894 | elseif channel == Wireless.Channels.UltimateDoorlockRequestReply then | |
| 895 | if message.content == true then | |
| 896 | SetText(nil, 'Opening Door', colours.green) | |
| 897 | else | |
| 898 | SetText(nil, ' Access Denied', colours.red) | |
| 899 | end | |
| 900 | end | |
| 901 | end | |
| 902 | end | |
| 903 | ||
| 904 | function FingerprintIsOnWhitelist(fingerprint) | |
| 905 | if Current.Settings.Whitelist then | |
| 906 | for i, f in ipairs(Current.Settings.Whitelist) do | |
| 907 | if f == fingerprint then | |
| 908 | return true | |
| 909 | end | |
| 910 | end | |
| 911 | end | |
| 912 | return false | |
| 913 | end | |
| 914 | ||
| 915 | function SaveSettings() | |
| 916 | Current.Settings = Current.Settings or {}
| |
| 917 | local h = fs.open('.settings', 'w')
| |
| 918 | if h then | |
| 919 | h.write(textutils.serialize(Current.Settings)) | |
| 920 | end | |
| 921 | h.close() | |
| 922 | end | |
| 923 | ||
| 924 | local closeDoorTimer = nil | |
| 925 | function OpenDoor() | |
| 926 | if Current.Settings and Current.Settings.RedstoneSide then | |
| 927 | SetText(nil, 'Opening Door', colours.green) | |
| 928 | redstone.setOutput(Current.Settings.RedstoneSide, true) | |
| 929 | closeDoorTimer = os.startTimer(0.6) | |
| 930 | end | |
| 931 | end | |
| 932 | ||
| 933 | function CloseDoor() | |
| 934 | if Current.Settings and Current.Settings.RedstoneSide then | |
| 935 | if redstone.getOutput(Current.Settings.RedstoneSide) then | |
| 936 | SetText(nil, 'Closing Door', colours.orange) | |
| 937 | redstone.setOutput(Current.Settings.RedstoneSide, false) | |
| 938 | end | |
| 939 | end | |
| 940 | end | |
| 941 | ||
| 942 | DefaultSettings = {
| |
| 943 | Whitelist = {},
| |
| 944 | RedstoneSide = 'back', | |
| 945 | Distance = 10 | |
| 946 | } | |
| 947 | ||
| 948 | function RegisterPDA(event, drive) | |
| 949 | if disk.hasData(drive) then | |
| 950 | local _fs = fs | |
| 951 | if OneOS then | |
| 952 | _fs = OneOS.FS | |
| 953 | end | |
| 954 | local path = disk.getMountPath(drive) | |
| 955 | local addStartup = true | |
| 956 | if _fs.exists(path..'/System/') then | |
| 957 | path = path..'/System/' | |
| 958 | addStartup = false | |
| 959 | end | |
| 960 | local fingerprint = nil | |
| 961 | if _fs.exists(path..'/.fingerprint') then | |
| 962 | local h = _fs.open(path..'/.fingerprint', 'r') | |
| 963 | if h then | |
| 964 | local str = h.readAll() | |
| 965 | if #str == 256 then | |
| 966 | fingerprint = str | |
| 967 | end | |
| 968 | end | |
| 969 | h.close() | |
| 970 | end | |
| 971 | if not fingerprint then | |
| 972 | fingerprint = GenerateFingerprint() | |
| 973 | local h = _fs.open(path..'/.fingerprint', 'w') | |
| 974 | h.write(fingerprint) | |
| 975 | h.close() | |
| 976 | if addStartup then | |
| 977 | local h = fs.open(shell.getRunningProgram(), 'r') | |
| 978 | local startup = h.readAll() | |
| 979 | h.close() | |
| 980 | local h = _fs.open(path..'/startup', 'w') | |
| 981 | h.write(startup) | |
| 982 | h.close() | |
| 983 | end | |
| 984 | end | |
| 985 | if not FingerprintIsOnWhitelist(fingerprint) then | |
| 986 | table.insert(Current.Settings.Whitelist, fingerprint) | |
| 987 | SaveSettings() | |
| 988 | end | |
| 989 | disk.eject(drive) | |
| 990 | SetText(nil, 'Registered Pocket Computer', colours.green) | |
| 991 | end | |
| 992 | end | |
| 993 | ||
| 994 | function HostSetup() | |
| 995 | ResetPage() | |
| 996 | Current.Page = 'HostSetup' | |
| 997 | Current.ButtonTwo = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, HostStatusPage, 'Save', colours.black) | |
| 998 | if not Current.Settings then | |
| 999 | Current.Settings = DefaultSettings | |
| 1000 | end | |
| 1001 | ||
| 1002 | local sideButtons = {}
| |
| 1003 | local function resetSideToggle(self) | |
| 1004 | for i, v in ipairs(sideButtons) do | |
| 1005 | if v.Toggle ~= nil then | |
| 1006 | v.Toggle = false | |
| 1007 | end | |
| 1008 | end | |
| 1009 | Current.Settings.RedstoneSide = self.Text:lower() | |
| 1010 | SaveSettings() | |
| 1011 | end | |
| 1012 | ||
| 1013 | table.insert(Current.PageControls, Label:Initialise(2, 2, 'Redstone Side')) | |
| 1014 | sideButtons = {
| |
| 1015 | Button:Initialise(2, 4, nil, nil, nil, nil, resetSideToggle, 'Back', colours.black, false, colours.green), | |
| 1016 | Button:Initialise(9, 4, nil, nil, nil, nil, resetSideToggle, 'Front', colours.black, false, colours.green), | |
| 1017 | Button:Initialise(2, 6, nil, nil, nil, nil, resetSideToggle, 'Left', colours.black, false, colours.green), | |
| 1018 | Button:Initialise(9, 6, nil, nil, nil, nil, resetSideToggle, 'Right', colours.black, false, colours.green), | |
| 1019 | Button:Initialise(2, 8, nil, nil, nil, nil, resetSideToggle, 'Top', colours.black, false, colours.green), | |
| 1020 | Button:Initialise(8, 8, nil, nil, nil, nil, resetSideToggle, 'Bottom', colours.black, false, colours.green) | |
| 1021 | } | |
| 1022 | for i, v in ipairs(sideButtons) do | |
| 1023 | if v.Text:lower() == Current.Settings.RedstoneSide then | |
| 1024 | v.Toggle = true | |
| 1025 | end | |
| 1026 | table.insert(Current.PageControls, v) | |
| 1027 | end | |
| 1028 | ||
| 1029 | local distanceButtons = {}
| |
| 1030 | local function resetDistanceToggle(self) | |
| 1031 | for i, v in ipairs(distanceButtons) do | |
| 1032 | if v.Toggle ~= nil then | |
| 1033 | v.Toggle = false | |
| 1034 | end | |
| 1035 | end | |
| 1036 | if self.Text == 'Small' then | |
| 1037 | Current.Settings.Distance = 5 | |
| 1038 | elseif self.Text == 'Normal' then | |
| 1039 | Current.Settings.Distance = 10 | |
| 1040 | elseif self.Text == 'Far' then | |
| 1041 | Current.Settings.Distance = 15 | |
| 1042 | end | |
| 1043 | SaveSettings() | |
| 1044 | end | |
| 1045 | ||
| 1046 | table.insert(Current.PageControls, Label:Initialise(23, 2, 'Opening Distance')) | |
| 1047 | distanceButtons = {
| |
| 1048 | Button:Initialise(23, 4, nil, nil, nil, nil, resetDistanceToggle, 'Small', colours.black, false, colours.green), | |
| 1049 | Button:Initialise(31, 4, nil, nil, nil, nil, resetDistanceToggle, 'Normal', colours.black, false, colours.green), | |
| 1050 | Button:Initialise(40, 4, nil, nil, nil, nil, resetDistanceToggle, 'Far', colours.black, false, colours.green) | |
| 1051 | } | |
| 1052 | for i, v in ipairs(distanceButtons) do | |
| 1053 | if v.Text == 'Small' and Current.Settings.Distance == 5 then | |
| 1054 | v.Toggle = true | |
| 1055 | elseif v.Text == 'Normal' and Current.Settings.Distance == 10 then | |
| 1056 | v.Toggle = true | |
| 1057 | elseif v.Text == 'Far' and Current.Settings.Distance == 15 then | |
| 1058 | v.Toggle = true | |
| 1059 | end | |
| 1060 | table.insert(Current.PageControls, v) | |
| 1061 | end | |
| 1062 | ||
| 1063 | table.insert(Current.PageControls, Label:Initialise(2, 10, 'Registered PDAs: '..#Current.Settings.Whitelist)) | |
| 1064 | table.insert(Current.PageControls, Button:Initialise(2, 12, nil, nil, nil, nil, function()Current.Settings.Whitelist = {}HostSetup()end, 'Unregister All', colours.black))
| |
| 1065 | ||
| 1066 | ||
| 1067 | table.insert(Current.PageControls, Label:Initialise(23, 6, 'Help', colours.black)) | |
| 1068 | local helpLines = {
| |
| 1069 | Label:Initialise(23, 8, 'To register a new PDA simply', colours.black), | |
| 1070 | Label:Initialise(23, 9, 'place a Disk Drive next to', colours.black), | |
| 1071 | Label:Initialise(23, 10, 'the computer, then put the', colours.black), | |
| 1072 | Label:Initialise(23, 11, 'PDA in the Drive, it will', colours.black), | |
| 1073 | Label:Initialise(23, 12, 'register automatically. If', colours.black), | |
| 1074 | Label:Initialise(23, 13, 'it worked it will eject.', colours.black), | |
| 1075 | Label:Initialise(23, 15, 'Make sure you hide this', colours.red), | |
| 1076 | Label:Initialise(23, 16, 'computer away from the', colours.red), | |
| 1077 | Label:Initialise(23, 17, 'door! (other people)', colours.red) | |
| 1078 | } | |
| 1079 | for i, v in ipairs(helpLines) do | |
| 1080 | table.insert(Current.PageControls, v) | |
| 1081 | end | |
| 1082 | ||
| 1083 | ||
| 1084 | table.insert(Current.PageControls, Button:Initialise(2, 14, nil, nil, nil, nil, function() | |
| 1085 | for i = 1, 6 do | |
| 1086 | helpLines[i].TextColour = colours.green | |
| 1087 | end | |
| 1088 | end, 'Register New PDA', colours.black)) | |
| 1089 | ||
| 1090 | end | |
| 1091 | ||
| 1092 | function HostStatusPage() | |
| 1093 | ResetPage() | |
| 1094 | Current.Page = 'HostStatus' | |
| 1095 | Current.StatusScreen = true | |
| 1096 | Current.ButtonOne = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, Quit, 'Quit', colours.black) | |
| 1097 | Current.ButtonTwo = Button:Initialise(2, Drawing.Screen.Height - 1, nil, nil, nil, nil, HostSetup, 'Settings/Help', colours.black) | |
| 1098 | ||
| 1099 | Wireless.Responder = function(event, side, channel, replyChannel, message, distance) | |
| 1100 | if channel == Wireless.Channels.UltimateDoorlockRequest and distance < Current.Settings.Distance then | |
| 1101 | if FingerprintIsOnWhitelist(message.content) then | |
| 1102 | OpenDoor() | |
| 1103 | Wireless.SendMessage(Wireless.Channels.UltimateDoorlockRequestReply, true) | |
| 1104 | else | |
| 1105 | Wireless.SendMessage(Wireless.Channels.UltimateDoorlockRequestReply, false) | |
| 1106 | end | |
| 1107 | end | |
| 1108 | end | |
| 1109 | ||
| 1110 | PingPocketComputers() | |
| 1111 | end | |
| 1112 | ||
| 1113 | function HostInitialise() | |
| 1114 | if not Wireless.Present() then | |
| 1115 | Current.Locked = true | |
| 1116 | Current.ButtonOne = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, Quit, 'Quit', colours.black) | |
| 1117 | Current.ButtonTwo = Button:Initialise(2, Drawing.Screen.Height - 1, nil, nil, nil, nil, function()os.reboot()end, 'Reboot', colours.black) | |
| 1118 | ResetStatus() | |
| 1119 | return | |
| 1120 | end | |
| 1121 | Wireless.Initialise() | |
| 1122 | ResetStatus() | |
| 1123 | if fs.exists('.settings') then
| |
| 1124 | local h = fs.open('.settings', 'r')
| |
| 1125 | if h then | |
| 1126 | Current.Settings = textutils.unserialize(h.readAll()) | |
| 1127 | end | |
| 1128 | h.close() | |
| 1129 | HostStatusPage() | |
| 1130 | else | |
| 1131 | HostSetup() | |
| 1132 | end | |
| 1133 | if OneOS then | |
| 1134 | OneOS.CanClose = function() | |
| 1135 | CloseDoor() | |
| 1136 | return true | |
| 1137 | end | |
| 1138 | end | |
| 1139 | end | |
| 1140 | ||
| 1141 | local pingTimer = nil | |
| 1142 | function PingPocketComputers() | |
| 1143 | Wireless.SendMessage(Wireless.Channels.UltimateDoorlockPing, 'Ping!', Wireless.Channels.UltimateDoorlockRequest) | |
| 1144 | pingTimer = os.startTimer(0.5) | |
| 1145 | end | |
| 1146 | ||
| 1147 | function Initialise(arg) | |
| 1148 | EventRegister('mouse_click', TryClick)
| |
| 1149 | EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
| |
| 1150 | EventRegister('mouse_scroll', Scroll)
| |
| 1151 | EventRegister('key', HandleKey)
| |
| 1152 | EventRegister('char', HandleKey)
| |
| 1153 | EventRegister('timer', Timer)
| |
| 1154 | EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
| |
| 1155 | EventRegister('modem_message', Wireless.HandleMessage)
| |
| 1156 | EventRegister('disk', RegisterPDA)
| |
| 1157 | ||
| 1158 | if OneOS then | |
| 1159 | OneOS.RequestRunAtStartup() | |
| 1160 | end | |
| 1161 | ||
| 1162 | if pocket then | |
| 1163 | PocketInitialise() | |
| 1164 | else | |
| 1165 | HostInitialise() | |
| 1166 | end | |
| 1167 | ||
| 1168 | ||
| 1169 | Draw() | |
| 1170 | ||
| 1171 | EventHandler() | |
| 1172 | end | |
| 1173 | ||
| 1174 | function Timer(event, timer) | |
| 1175 | if timer == pingTimer then | |
| 1176 | PingPocketComputers() | |
| 1177 | elseif timer == closeDoorTimer then | |
| 1178 | CloseDoor() | |
| 1179 | elseif timer == statusResetTimer then | |
| 1180 | ResetStatus() | |
| 1181 | end | |
| 1182 | end | |
| 1183 | ||
| 1184 | local ignoreNextChar = false | |
| 1185 | function HandleKey(...) | |
| 1186 | local args = {...}
| |
| 1187 | local event = args[1] | |
| 1188 | local keychar = args[2] | |
| 1189 | --[[ | |
| 1190 | --Mac left command character | |
| 1191 | if event == 'key' and keychar == keys.leftCtrl or keychar == keys.rightCtrl or keychar == 219 then | |
| 1192 | isControlPushed = true | |
| 1193 | controlPushedTimer = os.startTimer(0.5) | |
| 1194 | elseif isControlPushed then | |
| 1195 | if event == 'key' then | |
| 1196 | if CheckKeyboardShortcut(keychar) then | |
| 1197 | isControlPushed = false | |
| 1198 | ignoreNextChar = true | |
| 1199 | end | |
| 1200 | end | |
| 1201 | elseif ignoreNextChar then | |
| 1202 | ignoreNextChar = false | |
| 1203 | elseif Current.TextInput then | |
| 1204 | if event == 'char' then | |
| 1205 | Current.TextInput:Char(keychar) | |
| 1206 | elseif event == 'key' then | |
| 1207 | Current.TextInput:Key(keychar) | |
| 1208 | end | |
| 1209 | end | |
| 1210 | ]]-- | |
| 1211 | end | |
| 1212 | ||
| 1213 | --[[ | |
| 1214 | Check if the given object falls under the click coordinates | |
| 1215 | ]]-- | |
| 1216 | function CheckClick(object, x, y) | |
| 1217 | if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then | |
| 1218 | return true | |
| 1219 | end | |
| 1220 | end | |
| 1221 | ||
| 1222 | --[[ | |
| 1223 | Attempt to clicka given object | |
| 1224 | ]]-- | |
| 1225 | function DoClick(object, side, x, y, drag) | |
| 1226 | local obj = GetAbsolutePosition(object) | |
| 1227 | obj.Width = object.Width | |
| 1228 | obj.Height = object.Height | |
| 1229 | if object and CheckClick(obj, x, y) then | |
| 1230 | return object:Click(side, x - object.X + 1, y - object.Y + 1, drag) | |
| 1231 | end | |
| 1232 | end | |
| 1233 | ||
| 1234 | --[[ | |
| 1235 | Try to click at the given coordinates | |
| 1236 | ]]-- | |
| 1237 | function TryClick(event, side, x, y, drag) | |
| 1238 | if Current.ButtonOne then | |
| 1239 | if DoClick(Current.ButtonOne, side, x, y, drag) then | |
| 1240 | Draw() | |
| 1241 | return | |
| 1242 | end | |
| 1243 | end | |
| 1244 | ||
| 1245 | if Current.ButtonTwo then | |
| 1246 | if DoClick(Current.ButtonTwo, side, x, y, drag) then | |
| 1247 | Draw() | |
| 1248 | return | |
| 1249 | end | |
| 1250 | end | |
| 1251 | ||
| 1252 | for i, v in ipairs(Current.PageControls) do | |
| 1253 | if DoClick(v, side, x, y, drag) then | |
| 1254 | Draw() | |
| 1255 | return | |
| 1256 | end | |
| 1257 | end | |
| 1258 | ||
| 1259 | Draw() | |
| 1260 | end | |
| 1261 | ||
| 1262 | function Scroll(event, direction, x, y) | |
| 1263 | if Current.Window and Current.Window.OpenButton then | |
| 1264 | Current.Document.Scroll = Current.Document.Scroll + direction | |
| 1265 | if Current.Window.Scroll < 0 then | |
| 1266 | Current.Window.Scroll = 0 | |
| 1267 | elseif Current.Window.Scroll > Current.Window.MaxScroll then | |
| 1268 | Current.Window.Scroll = Current.Window.MaxScroll | |
| 1269 | end | |
| 1270 | Draw() | |
| 1271 | elseif Current.ScrollBar then | |
| 1272 | if Current.ScrollBar:DoScroll(direction*2) then | |
| 1273 | Draw() | |
| 1274 | end | |
| 1275 | end | |
| 1276 | end | |
| 1277 | ||
| 1278 | --[[ | |
| 1279 | Registers functions to run on certain events | |
| 1280 | ]]-- | |
| 1281 | function EventRegister(event, func) | |
| 1282 | if not Events[event] then | |
| 1283 | Events[event] = {}
| |
| 1284 | end | |
| 1285 | ||
| 1286 | table.insert(Events[event], func) | |
| 1287 | end | |
| 1288 | ||
| 1289 | --[[ | |
| 1290 | The main loop event handler, runs registered event functinos | |
| 1291 | ]]-- | |
| 1292 | function EventHandler() | |
| 1293 | while isRunning do | |
| 1294 | local event, arg1, arg2, arg3, arg4, arg5, arg6 = os.pullEventRaw() | |
| 1295 | if Events[event] then | |
| 1296 | for i, e in ipairs(Events[event]) do | |
| 1297 | e(event, arg1, arg2, arg3, arg4, arg5, arg6) | |
| 1298 | end | |
| 1299 | end | |
| 1300 | end | |
| 1301 | end | |
| 1302 | ||
| 1303 | function Quit() | |
| 1304 | isRunning = false | |
| 1305 | term.setCursorPos(1,1) | |
| 1306 | term.setBackgroundColour(colours.black) | |
| 1307 | term.setTextColour(colours.white) | |
| 1308 | term.clear() | |
| 1309 | if OneOS then | |
| 1310 | OneOS.Close() | |
| 1311 | end | |
| 1312 | end | |
| 1313 | ||
| 1314 | if not term.current then -- if not 1.6 | |
| 1315 | print('Because it requires pocket computers, Ultimate Door Lock requires ComputerCraft 1.6. Please update to 1.6 to use Ultimate Door Lock.')
| |
| 1316 | elseif not (OneOS and pocket) and term.isColor and term.isColor() then | |
| 1317 | -- If the program crashes close the door and reboot | |
| 1318 | local _, err = pcall(Initialise) | |
| 1319 | if err then | |
| 1320 | CloseDoor() | |
| 1321 | term.setCursorPos(1,1) | |
| 1322 | term.setBackgroundColour(colours.black) | |
| 1323 | term.setTextColour(colours.white) | |
| 1324 | term.clear() | |
| 1325 | print('Ultimate Door Lock has crashed')
| |
| 1326 | print('To maintain security, the computer will reboot.')
| |
| 1327 | print('If you are seeing this alot try turning off all Pocket Computers or reinstall.')
| |
| 1328 | print() | |
| 1329 | print('Error:')
| |
| 1330 | printError(err) | |
| 1331 | sleep(5) | |
| 1332 | os.reboot() | |
| 1333 | end | |
| 1334 | elseif OneOS and pocket then | |
| 1335 | term.setCursorPos(1,3) | |
| 1336 | term.setBackgroundColour(colours.white) | |
| 1337 | term.setTextColour(colours.blue) | |
| 1338 | term.clear() | |
| 1339 | print('OneOS already acts as a door key. Simply place your PDA in the door\'s disk drive to register it.')
| |
| 1340 | print() | |
| 1341 | print('To setup a door, run this program on an advanced computer (non-pocket).')
| |
| 1342 | print() | |
| 1343 | print('Click anywhere to quit')
| |
| 1344 | os.pullEvent('mouse_click')
| |
| 1345 | Quit() | |
| 1346 | else | |
| 1347 | print('Ultimate Door Lock requires an advanced (gold) computer or pocket computer.')
| |
| 1348 | end |