Перейти к содержимому

Zer0Galaxy

Гуру
  • Публикации

    1 220
  • Зарегистрирован

  • Посещение

  • Победитель дней

    189

Сообщения, опубликованные пользователем Zer0Galaxy


  1. Многопоточность в CraftOS легко реализуется при помощи стандартной библиотеки parallel. Способ этот отличается простотой и может быть использован даже начинающими программистами. Чего уж проще? Оформи каждый поток в виде отдельной функции и вызови waitForAll или waitForAny.

    Но такая многопоточность обладает, на мой взгляд, несколькими несущественными недостатками.

    Во-первых, пока работает parallel, основная нить программы приостанавливается и занимается исключительно обслуживанием параллельных потоков.

    Во-вторых, функции, содержащие параллельные потоки, обречены вызываться без параметров.

    В-третьих, после запуска такая параллельность не контролируема. Отсутствует возможность принудительно прервать какой либо из потоков или добавить к уже существующим еще один.

     

    Несколько иную многопоточность можно реализовать при помощи библиотеки thread, доступной по адресу http://pastebin.com/32S4HssH

    Библиотека содержит три функции:

    thread.create(f , ...) - создает поток, который сразу же начинает выполняться параллельно основному потоку. При желании можно создать серию потоков, вызвав функцию create несколько раз подряд. В качестве параметра f необходимо указать функцию, содержащую тело потока. После f  можно указать параметры, передаваемые ей.

    Функция create возвращает вновь созданный поток как объект типа нить ("thread"). Значение это может понадобиться если вы захотите прервать принудительно созданный поток.

    thread.kill(co) - прерывает выполнение параллельного потока. co - завершаемый поток, значение, полученное при вызове функции create.

    thread.killAll() - прекращает выполнение всех параллельных потоков, за исключением основного. Вызывать эту функцию полезно перед завершением программы. В противном случае действующие потоки продолжат свою работу даже после выхода из программы.

    • Нравится 8

  2.  Так что, наверное, придется использовать связку сервер-клиент: пишем на клиент-компьютере программу и она отсылается на сервер на выполнение.

    Это тоже вариант. Но у нас решен вопрос защиты кода от коррекции. Конечно и ее можно обойти, но это будет не проще чем решить головоломку.


  3. На черепахе сохраняешь под именем startup программу

     

     

    function open()
      local bOpen, sFreeSide = false, nil
      for n,sSide in pairs(rs.getSides()) do
        if peripheral.getType( sSide ) == "modem" then
          sFreeSide = sSide
          if rednet.isOpen( sSide ) then
            bOpen = true
            break
          end
        end
      end
      if not bOpen then
        if sFreeSide then
          print( "No modem active. Opening "..sFreeSide.." modem" )
          rednet.open( sFreeSide )
          return true
        else
          print( "No modem attached" )
          return false
        end
      end
      return true
    end
    
    if not open() then return end
    print("ID of this turtle is ",os.getComputerID())
    while true do
      id,comm=rednet.receive()
      print(comm)
      pcall(shell.run,comm)
    end
    

     

     

    Перегружаешь черепаху

     

    На компьютере сохраняешь под именем tclient программу

     

     

    function open()
      local bOpen, sFreeSide = false, nil
      for n,sSide in pairs(rs.getSides()) do
        if peripheral.getType( sSide ) == "modem" then
          sFreeSide = sSide
          if rednet.isOpen( sSide ) then
            bOpen = true
            break
          end
        end
      end
      if not bOpen then
        if sFreeSide then
          print( "No modem active. Opening "..sFreeSide.." modem" )
          rednet.open( sFreeSide )
          return true
        else
          print( "No modem attached" )
          return false
        end
      end
      return true
    end
    
    if not open() then return end
    Arg={...}
    if #Arg~=1 then print("Usage: tclient <turtleID>") return end
    tID=tonumber(Arg[1])
    if not tID then print("Usage: tclient <turtleID>") return end
    print("Type 'exit' to terminate programm")
    while true do
      write("command:")
      comm=read()
      if comm=="exit" then return end
      rednet.send(tID,comm)
    end
    
    

     

     

    Запуск: tclient <ID черепахи>

    Проверишь, отпиши результат


  4. Есть пара вопросов.

    1. Тебе нужно готовое решение или ты хочешь сам написать такую программу с нашей помощью, разумеется? 

    2. Удаленно необходимо выполнять любую доступную черепахе команду в плоть до программирования самой черепахи (т.е. удаленный терминал) или строго ограниченный набор команд?

     

    И не надо так кричать


  5. Сделать комнату со стенами из сенсорных мониторов. На них изображены устройства, двери и т.д. Решил головоломку - "дверь" разблокировалась, можно "идти" в следующую "комнату" (Фон, расположение дверей и головоломки изменятся). Тогда игрок сможет сам решать, что ему проходить

    А слабО головоломку придумать? А запрограммировать?

    Я начал было делать серию комнат на старом сервере. Даже несколько дверей вместе с Нео запрограммировали.

    А вот на новый сервер зайти не могу.


  6. Если же ты хочешь просто разобраться с coroutine то это отдельная песня, мало связанная с параллельным выполнением.

    Библиотека coroutine позволяет создавать т.н. сопрограммы. Это такие функции, допускающие вход не с начала, а с того места, на котором в прошлый раз сопрограмма прервала свое выполнение. Но на мой взгляд, без сопрограмм прекрасно можно обойтись имея библиотеку parallel.

    • Нравится 2

  7. Сам по себе coroutine не сильно удобен для распараллеливания потоков. Распараллеливание проще всего реализовать при помощи библиотеки parallel. Просто оформляешь каждый поток в виде отдельной функции и вызываешь parallel.waitForAll или parallel.waitForAny.

    Но, доложен сказать, что если каждый из потоков будет выполнять rednet.receive то смысла в распараллеливании особого нет. Ты просто получишь принятую по rednet строку в нескольких экземплярах. parallel полезен при ожидании совершенно разных событий, например, приема по rednet и ввода с клавиатуры через read()


  8.  

    EEPROM

    Что это такое, и зачем оно?

    Это новый предмет, который необходим всем девайсам - компьютерам, серверам, роботам, планшетам - чтобы с него загружаться. Он содержит часть кода, которая прежде была жестко вписана в сам мод. Этот код - первое, что загружает компьютер при включении. 

    Я правильно понял, теперь что бы включить новый компьютер одной OP-дискеты не достаточно? Нужно еще Lua BIOS EEPROM. Или можно загрузиться только с EEPROM?


  9. На сколько знаю, ОС-компьютер продолжает работать с того места, где его прервали. А вот сокет врядли восстановится. Так что, скорее всего, будет потеря соединения. Компьютер должен периодически контролировать соединение и восстанавливать в случае потери.

    • Нравится 1

  10. зеро зачем тебе это?

    Два СС-клиента с CraftNet-адресами route1.client1 и route2.client2 конектятся к ОС-шлюзу.

    Шлюз цепляется к мосту и регистрирует два канала "route1.client1" и "route2.client2"

    С другой стороны моста цепляются два Android-приложения, одно к каналу "route1.client1", другое - к "route2.client2"

    Всё, что шлюз получает по каналу "routeN.clientN" он транслирует соответствующему клиенту через CraftNet. И наоборот.

    Нужно только, что бы шлюз мог определять по какому каналу он получил посылку.

    Такая схема позволит пользоваться мостом не только ОС, но и СС-компьютерам.


  11. А есть ли возможность ОС-компьютер включить в Craftnet?

    СС-компьютер подключается по Craftnet к ОС-компьютеру. То подключается к мосту и регистрирует канал с именем, совпадающим с адресом СС-компьютера. Может ли такой ОС-компьютер обслуживать несколько клиентов?


  12. Можно задавать количество повторений в виде числа. Скажем так:

    local function man(algo)
         for v,d in string.gmatch(algo, "(%a)(%d*)") do
         d=tonumber(d) or 1
         for i=1,d do
          if (v == "l") then turtle.turnLeft()
          elseif (v == "r") then turtle.turnRight()
          elseif (v == "f") then turtle.forward()
          elseif (v == "u") then turtle.up()
          elseif (v == "d") then turtle.down()
          elseif (v == "b") then turtle.back()
          elseif (v == "p") then print("lol")
          else print("Impossible algorithm.") return false
          end
         end
         end
         return true
        end
    

    Тогда алгоритм будет выглядеть как-то так "f30u15rf10".

    • Нравится 1

  13. Есть ли в крафт-нете а) резервирование адресов; б) обращение по именам?

     

    p.s. функционал DNS.

    Craftnet-адрес представляет собой несколько строк, разделенных символом точка, т.е. нечто среднее между ip- адресом и DNS именем. Обычно клиенту выдается адрес, состоящий из имени сегмента, имени роутера и id компьютера-клиента. Но могут быть и исключения, нужно лишь договориться с админом сети.


  14. Даешь объяснение!

    Виртуальный мир, как и мир Minecraft, имеет систему координат x,y,z. Ось x условно направлена слева направо (в сторону возрастания координаты). Ось y - снизу вверх. Ось z - вперед. Да, несоответствие с миром Minecraft, где ось z направлена назад, т.е. на юг. Но так сделано. Единица длины виртуального мира в точности соответствует размеру одного блока. Плоскость y=0 соответствует поверхности земли.

    Прежде чем что-то делать в виртуальном мире, его нужно создать функцией

    CreateWorld(mfront,mleft,mright,mback [,clgnd [,clsky]])

    Она инициализирует наш виртуальный мир. Первые четыре параметра, которые она принимает - мониторы, на которых будет выводиться изображение. Сюда нужно подставить строки типа "monitor_N" или nil, если соответствующий монитор не используется.

    Два опциональных параметра clgnd и clsky задают цвет земли и неба в нашем мире. По умолчанию земля - зеленая, небо - голубое.

     

    Сразу после создания мира наблюдатель (точнее его глаза) находится в точке x=0, y=1.62, z=0

    Для перемещения наблюдателя и контроля его положения служат функции:

    x,y,z=getPlayerPos() - возвращает координаты глаз наблюдателя

    setPlayerPos(x,y,z) - перемещает глаза наблюдателя в точку с указанными координатами

    movePlayer(x,y,z) - смещает наблюдателя на указанный вектор.

     

    Объекты в виртуальном мире создаются функцией

    obj=CreateObj(x,y,z,paint,params)

    где x,y,z - координаты точки привязки объекта, такой точки относительно которой объект будет прорисовываться;

    paint - функция прорисовки объекта (о ней чуть позже)

    params - необязательная таблица параметров объекта, его свойства, зависящие от самого объекта

    Функция CreateObj возвращает указатель на созданный объект, который в дальнейшем можно использовать для перемещения объекта или изменения его свойств.

    Все создаваемые объекты пока фантомные т.е. их видно, но они никак не взаимодействуют друг с другом и не препятствуют перемещению наблюдателя.

     

    Создание объекта не приводит к его моментальной прорисовке, а только к сохранению объекта в памяти компьютера. Прорисовкой занимается функция

    draw()

    Она выводит на мониторы виртуальный мир так как его бы видел наблюдатель. Функцию draw надо вызывать после создания объектов, изменения их свойств и/или перемещения наблюдателя.

    • Нравится 3
×
×
  • Создать...