swg2you
-
Публикации
219 -
Зарегистрирован
-
Посещение
-
Победитель дней
20
Сообщения, опубликованные пользователем swg2you
-
-
Захотелось мне найти значения безопасных цветов, чтобы разноцветные программы одинаково отображались на мониторах 2-го и 3-го уровня.
Затем мне захотелось найти простую формулу для генерации палитры 6*8*5 + 16 оттенков серого, для мониторов 3-го уровня.
В процессе изысканий родился инструмент Sipmle color tester или sicot.lua:local gpu=require('component').gpu local ev=require('event') local function setColor(f,b) gpu.setForeground(f) gpu.setBackground(b) end local w=0xFFFFFF require('term').clear() gpu.fill(1,1,80,12," ") gpu.set(27,1,'← click →') gpu.set(76,1,'ʕ▫ᴥ▫ʔ') gpu.set(69,3,'◄ Tier 2') gpu.set(69,5,'◄ Tier 3') gpu.set(69,6,' ▼') local t=ev.timer(1,function() if math.random(6)==1 then setColor(w,0) gpu.set(76,1,'ʕ▪ᴥ▪ʔ') os.sleep(.05) gpu.set(76,1,'ʕ▫ᴥ▫ʔ') end end, math.huge) local function showcolor(c) for i=0,24 do local b=bit32.extract(c,i,1) setColor((1-b)*w, b*w) gpu.set(24-i,1,tostring(b)) end setColor(bit32.bxor(c,w), c) gpu.fill(1,3,24,3," ") gpu.set(9,4,'0x'..string.format('%06X',c)) setColor(w,0) gpu.set(1,2,'└──┴┴──┘└──┴┴──┘└──┴┴──┘') end local color=math.random(w) showcolor(color) local s='SimpleColorTest' for i=1,#s do setColor(bit32.bxor(color,w), color) gpu.set(36+i*2,1,string.sub(s,i,i)..' ') color=math.random(w) end --Tier2: безопасная палитра, используйте эти цвета, чтобы ваша программа выглядела одинаково на мониторах 2-го и 3-го уровней palTier2={0x000000,0x333333,0x333399,0x336600,0x336699,0x33CC33,0x663300,0x6699FF,0x9933CC,0xCC66CC,0xCCCCCC,0xFF3333,0xFFCC33,0xFF6699,0xFFFF33,0xFFFFFF} for x=0,15 do setColor(w,palTier2[x+1]) gpu.set(36+2*x, 3, ' ') end --Tier3: 16 оттенков серого for y=0,0xF do setColor(w,y*0x111111) gpu.set(36+y*2, 5, ' ') end --Tier3: большая палитра 6*8*5=240 комбинаций цветов for r=0,5 do for g=0,7 do for b=0,4 do setColor(w, r*0x330000 + g*0x2400 + b*0x3F) gpu.set(1+2*(b+g*5), 7+r, ' ') end end end repeat local _,_,x,y,b=ev.pull('touch') local s,fg,bg=gpu.get(x,y) if y==1 and x<=24 then local bit=24-x color = bit32.bxor(color,2^bit) showcolor(color) else color=bg showcolor(color) end until b==1 ev.cancel(t) setColor(w,0) require('term').clear()
Так он выглядит не мониторе 3-го уровня:
А так, на мониторе 2-го уровня:
(Обратите внимание на то, что цвета ,безопасной палитры Tier 2 выглядят одинаково на обеих экранах!)На мониторе 1-го уровня он не выглядит никак.
В нем можно кликать по битам, и по цветным квадратикам.
(Только по медвежонку LiVi не кликайте, он этого не любит)
Внутри кода, вы можете найти безопасную палитру в 16 цветов, и простую формулу генерации большой палитры.
Код сырой и грубый, улучшать можно бесконечно. Навскидку:- Повесить резидентом, чтобы вызывался по хоткею, сохранял под собой экран, и выводился поверх.
- Добавить кнопочку "вставить цвет", которая в таймере будет имитировать ввод цветового кода.
- Переписать в виде библиотеки с выдачей/запросом/установкой цветов по индексу.
- Добавить таблицу комбинаций цветов текста и фона, для наглядности.
- Добавить определение цвета текста (а не только фона).
- Добавить в библиотеку аналог ANSI цветовых кодов.
- Научить LiVi танцевать.
- Что-то еще.
В процессе игры было обнаружено, что OC принудительно приводит цвета к стандартному значению. Т.е, какие бы вы цвета не писали, они будут приведены к 256 цветам в случае с T3 и к 16 - в случае с Т2. Это есть очень хорошо для хранения экранов во всяких многооконных бодягах. В самом худшем случае (присутствие всех возможных цветов), хранение полной цветовой плоскости экрана T3, без сжатия, займет 16000 байт, а T2 - 2000 байт.
Также была обнаружена дикость генерации 16 цветной палитры T2, кто найдет закономерность и простую формулу для генерации - тому печенька.
Еще был обнаружен аномальный, странный, неучтенный, нестандартный цвет на T2. Кто найдет 17-й цвет - тому две печеньки, и цвет в подарок.-
4
-
У одного меня родилась ассоциация : " Резидентная программа --> Вирус " ?
Это один из вариантов использования резидентных программ.
-
a=1 load(" print(a) load('print(a)')()",nil,nil,{print=print, load=load, a=2})()Результат:
2
1
Вывод: не хочешь давать доступ к руту - не разрешай в среде функцию load
Если это результат выполнения на одной из чистых реализаций, то этот баг вполне можно считать фичей.
Убрать load - не вариант. Придется учитывать эту особенность и исправлять поведение кода на более каноничное.
upd:
задал тот-же вопрос на стаковерфлоу, отвечают что если не указать среду лоад берет, цитирую: "very global environment" )
будем глушить. OpenOs то надо в окошке запустить.
-
В для первого load() ты указываешь переменную окружения, насколько я понял.
Для второго - нет (используется "глобальное окружение").
Поэтому, у них разные переменные а.
Да, но блок
[[
print(a)
load("print(a)")()
]]
скомпилирован в среде e.
Для этого блока глобальной средой является содержимое таблицы e. Т.е. все что находится в этом блоке не может видеть ничего кроме переданных функций print, load, заданной a и замыкающей _G.
Получается что load() игнорируя принципы Lua и собственную среду выполнения - получает доступ к рутовому глобалу, мало того, дает этот доступ компилируемому блоку.
На мой взгляд, это серьезный баг реализации, нарушающий общую концепцию изоляции сред в Lua. Либо я неверно понимаю эту концепцию.
upd:
если у кого-то установлен чистый Lua без майнкрафтов и прочих крафтов, прошу проверить, проявляется ли такой эффект там.
-
Да, действительно, выдает не то, что подразумевается. Но не 2,1 а 2, nil. Почему так происходит не в курсе, нужно видимо у самого Сангара спрашивать, либо копаться в реализации этого load() на гитхабе.
nil - это я первую строчку в примере потерял.
поправил пример.
-
А можно я по теме? Считаю, что хранить картинку в виде сериализованной таблицы крайне не рационально. Куча лишних скобок, пробелов и запятых. Не хочешь подумать над более компактным форматом?
Истина!
Таблицы громоздки. Хранение одного большого экрана отожрет почти всю планку памяти тиер1, строкой хранить на несколько порядков компактнее.
-
Ищи баг в программе

Никаких препятствий там нет и быть не может. Скорее всего, твой робот уперся в задницу криперу. Ее он, кстати, может принять за воздух=)
Заметил в шахтерских мирах одну особенность. Крипер, когда взрывается, визуально разрушает блоки. Но при попытке войти в этот блок, тебя выталкивает назад. Этакие прозрачные непроходимые блоки получаются.
Если попытаться установить что-то, в визуально отсутствующий блок, будь то булыжник или факел, исходный блок восстанавливается, а устанавливаемый итем возвращается в инвентарь.
Такой вот баг.
Нужно сходить с роботом в майнерс мир, подорвать крипера и потестить, что скажет робот при попытке прохождения через "невидимую стену" и как он её видит.
-
Такое происходит из-за биндинга, есть разница между статичным и динамичным.
Не понял.
load("print(a)") вызванный с параметрами "по умолчанию", должен компилировать блок "print(a)" в среде _G
Поскольку для load("print(a)") глобальной средой является e, то ожидается что именно e будет средой для "print(a)"
Но, почему-то, load берет среду из места в которое не должен иметь доступа.
-
пример кода:
a=1 local e={print=print, load=load, a='2'} e._G=e load( [[ print(a) load("print(a)")() ]] , '', '', e)()ожидается вывод:
2
2
а в реальности:
2
1
Проверял и под OpenOS и в чистой среде.
Это баг или фича? -
Notepad++/Опции/Настройки/Настройки табуляции/N++ 4 делает
-
1
-
-
2 Fingercomp
Мы пишем программы под ос выполняющуюся в интерпретаторе луа на эмулируемом модом железе внутри программы майнкрафт внутри джавы внутри ос внутри реального компьютера.
Вам не кажется это странным?
Одна причина, почему стоит писать свою ОС для этой матрешки:
- Это интересно и познавательно.
А всех кто вам скажет, что это бессмысленно отвечайте, - Кактус!
-
8
-
1
-
После h:close можно написать computer.beep.
Не вариант. Одиночный бип я могу и не услышать. Нужно чтобы хотя-бы раз в пару секунд бипать начал.
Тут либо делать поток thread, либо через подмену, либо посмотрев реализацию event.listen.
Как вариант, внутри обработчика входящих от модема можно повесить новый обработчик по таймеру
local beep=event.timer(1, function() computer.beep(440) end, math.huge)
а снаружи, добавить еще один, который будет слушать клавиатуру и по нажатию на клавишу делать
if beep then event.cancel(beep) end
upd:
Итак, совместные усилия превратились в код нового, хорошего и правильного tsrmail.lua
local port = 9 if _tsrmail then io.write('tsrmail already loaded @ port ',_tsrmail) else local beep, cp, ev = false, require("computer"), require("event") require("component").modem.open(port) local function listener(...) local e={...} if e[4] == port then local h = io.open('@','a') h:write('--', os.date(), ' from:', e[3], ' port:', e[4], '\n') h:write(table.concat(e,'\n',6)) h:close() if not beep then beep=ev.timer(2, function() cp.beep(440) end, math.huge) end end end local function unbeep() if beep then ev.cancel(beep) beep=false end end ev.listen("key_down", unbeep) ev.listen("modem_message", listener) io.write('tsrmail loaded @ port ', port) _G._tsrmail=port endСпасибо всем оппонентам, кто высказывался по делу:
Zer0Galaxy за, -можно повесить слушателя на событие
LeshaInc за, -покажу на примере
Fingercomp за, -события будут продолжать обрабатываться даже после завершения программы
Zer0Galaxy за, -можно еще порт и дистанцию прилепить
NEO за, -лучше io используй
И всем остальным за общее комментирование и множественные примеры.
-
Ох ты, набежали тут, примеров накидали ) я вообще-то с LeshaInc разговаривал ))Достаточно написать функцию-обработчик, типа этого:
Ну ладно, попробуйте event.listen повесить без OpenOS, и на этом закроем тему.
-
А как сделать, чтобы эта штука сигнализировала пользователю о том, что новое сообщение получено и записано в файл?event=require"event" function listmsg(eventName, receiverAddress, senderAddress, port, distance, ...) local h = fs.open('@','a') h:write('--'..os.date()..' From:'..senderAddress..'\n'..table.concat({...},'\n')) h:close() end event.listen("modem_message", listmsg)Как то так. Можно еще порт и дистанцию прилепить -
Как именно? Пример будет? Ждем.Заменить "print(msg)" в моём коде на запись в файл и все.
-
Первоисточник всего: http://www.lua.org/manual/5.2/manual.html#2.4Компьютер наилучшей комплектации отправлен на Мадагаскар хомячкам до востребования.
А какие еще интересные функции кроме __index и __newindex могут содержать метатаблицы?
-
Круто, а как сделать чтобы он не на экран выводил а в файл?после выполнения этого кода ты сможешь например запускать любые другие программы.
-
Это мелочи, мы всегда можем написатьТолько их там не 6. Если ты напишешь m.broadcast(port, data1)---их будет шесть,а если ты напишешь m.broadcast(port, data1, data2)---их будет 7, и так далее
local function listmsg(...) print(...) end event.listen("modem_message", listmsg)Главное суметь заставить работать это в фоне. Ждем LeshaInc, чтоб объяснил как это сделать.
т.е. этот код выполнится, оставит слушателя работать, а я смогу тем временем запускать другие программы?Листен всё держит в условном фоне
Ты просто заменяешь event.pull на event.listen(event, function) и всё
-
Гоу к нам в Opennet http://computercraft.ru/topic/675-opennetoc-prodolzhenie/
Если объеденяться, то твоя программа может сразу появляться у пользователя, а нам пригодятся твои идеи и реализации сетевых алгоритмов. У нас уже и адресная книга aka DNS есть, и пересылка порциями.
Я смотрел, но OpenNet пока слишком сложна для моего понимания. Не вижу общей концепции.
-
Через event.listen swg2you можешь повесить слушателя на modem_message. Вот если не знаешь его использование:
event.listen(event: string, function: function) -- Теперь если он словит event который указан в первом аргументе будет выполнена функция со второго аргумента. Аргументы функции нужно передавать такие же, какие выдаст event.pull, т е шесть аргументов.
Например:
local function listmsg(_,_,_,_,_,msg) print(msg) end event.listen("modem_message", listmsg)Такой код будет ловить сообщения по всем открытым портам и выводить их на экран.Уоу, круто!
А как это запустить чтоб оно работало в фоне?
-
Приз за решение проблемы ReadOnly-полей уходит к swg2you. Жду комплектацию компьютера и адрес куда его отправлять.
Хотелось бы узнать про параметры (t,k,v) функции __newindex. А про функции rawget и rawset поподробнее.
__newindex(t,k,v) - (новый индекс) вызовется если в таблицу t, несуществующему ключу k присвоить значение v
v=rawget(t,k) и rawset(t,k,v) - позволяют получить/присвоить значение v напрямую, игнорируя всякие метаметоды
Приз за решение проблемы прошу передать в международный фонд помощи мадагаскарским хомячкам.
-
Как ты верно подметил, если переименовать tsrmail обратно в tsrsniffer, то мы получим сетевой сниффер, который будет фоном перехватывать все! входящие пакеты на всех! портах и складывать их в файлик. )Так где здесь пересылка файлов? Эта штука абсолютно весь пойманный эфир (возможно не только 9-й порт) будет сыпать в один файл. И зачем переопределять функцию pullSignal если можно повесить слушателя на событие?
Более того, если удалить "=='modem_message'", то мы получим сниффер для всех событий.
upd:
моя не уметь на событие, моя уметь подменять pullSignal
-
Модуль отправки: send.lua
print('Use: send [<receiver-address>] < <filename> - for send filename,\nor: send [<receiver-address>] - for write, and Ctrl+C to send.') local port = 9 local c = require("component") local m = c.proxy(c.list("modem")()) local s, addr = io.read("*a"), ... if #s>0 then if addr then m.send(addr, port, s) else m.broadcast(port, s) end print('Sended: '..#s..' bytes') endи резидентный модуль приема: tsrmail.lua
local port = 9 if _tsrmail then print('tsrmail already loaded @ port '.._tsrmail) else local beep=0 local c = require("component") local cp = require("computer") local fs = require("filesystem") local m=c.proxy(c.list("modem")()) local pullSignal = cp.pullSignal cp.pullSignal = function (...) local e={pullSignal(...)} if e[1]=='modem_message' then local h = fs.open('@','a') h:write('--'..os.date()..' From:'..e[3]..'\n'..table.concat({table.unpack(e,6)},'\n')) h:close() beep=1 elseif e[1]=='key_down' then beep=0 elseif beep>0 then cp.beep(440) end beep=-beep return table.unpack(e) end m.open(port) print('tsrmail loaded @ port '..port) _G._tsrmail=port endсохранить на диск.
tsrmail.lua - запустить, после чего она останется резидентным модулем в памяти, и слушая 9-й порт, будет складывать всю почту в файл "@" на диске.
Пример использования:
У пользователя Коли, и еще у кого-то, есть компьютер с сетевой картой, на котором работает резидентная tsrmail.lua.
Программист Вася только что, получил на дискетке копию "TSR mail", запустил tsrmail.lua, чтобы иметь возможность принимать почту, и ему не терпится заявить о себе всему миру. Он запускает send, читает две строчки справки, пишет пару строк сообщения (хеловорд конечно, что же еще может написать программист) и нажав Ctrl+C отправляет.

Но пользователь Коля, как и другие пользователи "TSR mail" заняты своими делами: кормят коров, сажают желтые цветы и воюют с криперами. Хоть Колин компьютер и пищит "хозяин! почта пришла!", Коля далеко и не слышит.
Программисту Васе не терпится пообщаться, он хочет чтобы ему тоже прислали что-то. Хоть простенький хелловорд.
Немного поразмыслив, Вася соображает, что хелловорд это самодостаточная штука, и вовсе не располагает к ответам и общению. Заметив в первой строчке образец перенаправления ввода/вывода (а наш Вася программист, и знает всю мощь этого шаманства) он вновь запускает send отправляет сообщение и, поскольку под рукой больше ничего не нашлось, отправляет в сеть программку send.lua, направив содержимое send.lua во входной поток самой себя.

Пользователь Коля, проходив мимо компьютера, услышал писк и подошел проверить почту. Посмотрев стандартной командой cat @ содержимое файла @, с тремя сообщениями Васи, и пробурчав под нос, - Опять эти программеры фигней страдают, лучше бы коров покормили! - удалил сообщения командой rm @

Если бы наш программист догадался прислать что-то поинтереснее, например новую версию пасьянса, то Коля может и сохранил бы его, переименовав mv @ pasians2.lua, и почистив edit pasians2.lua от лишних сообщений.
Но к сожалению, это был не пасьянс.
--==--
P.S.
Код quick and dirty, но зато simple and short. По хорошему, нужна обертка-интерфейc для send, которая будет хранить адресную книгу, дополняя адресатов из @, большие файлы пересылать порциями обходя ограничение на размер пакета, красиво показывать @ добавляя функции ответа и сохранения, ну и все такое. А в резидентный модуль неплохо бы добавить отклик "принял".
-
3
-
-
Я далек от ООП, но думаю, что как-то так.Так, а как сделать что бы таблица ro была не одна на всех, а своя для каждого экземпляра класса?
setmetatable(obj1, {__index=ro1,__newindex=function(t,k,v) local _=rawget(ro1,k) or rawset(t,k,v) end})
setmetatable(obj2, {__index=ro2,__newindex=function(t,k,v) local _=rawget(ro2,k) or rawset(t,k,v) end})
Или по твоему коду:
Class={a=1, b=2} function Class:new() local obj={c=3, d=4} local nc={} for k,v in pairs(self) do nc[k]=v end setmetatable(obj,{__index=nc,__newindex=function(t,k,v) local _=rawget(nc,k) or rawset(t,k,v) end}) return obj end function Class:ShowFields() prn(self.a, self.b, self.c, self.d) end function Class:SetA(Val) rawset(self,'a',Val) end function Class:SetB(Val) rawset(self,'b',Val) end obj = Class:new() obj2 = Class:new() obj:ShowFields() obj.a=5 obj.b=6 obj.c=7 obj.d=8 obj:ShowFields() obj:SetA(5) obj:SetB(6) obj:ShowFields() obj2:ShowFields()Если я правильно понял, что тебе от этого кода нужно.

Подмена computer.pullSignal или методика построения резидентных программ в OpenOS
в Гайды
Опубликовано:
Службы, демоны, резиденты - каких только имен не наплодили для фоновых задач )