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

RccHD

Пользователи
  • Публикации

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

  • Посещение

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

    13

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


  1. Предисловие

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

     


    Описание моей библиотеки

    Здесь особо описывать нечего, поэтому я просто приложил примеры кода( комментарии обязательны к прочтению! )
     

    1. Создание класса



    local Class = require("class")
    
    -- Класс для точки в 2д пространстве
    local Point2d = Class({
        -- Конструктор класса
        __init__ = function(self, x, y)
            self.x, self.y = x, y
        end,
        
        -- Методы класса
        -- Примечание:
        --   аргументы каждого метода класса обязательно
        --   должны начинаться с "self" (ну, либо с "this" или "it", кому как угодно)
        printCoords = function(self)
            print("X = ".. self.x .."; Y = ".. self.y)
        end
    })
    
    -- Создание экземпляра класса Point2d
    local p1 = Point2d(5, 11)
    -- Вызов метода
    p1.printCoords() -- Выведет "X = 5; Y = 11"
    
    
    local p2 = Point2d(p1.x * 2, p1.y * 2)
    p2.printCoords() -- Выведет "X = 10; Y = 22"
    
    

    2. Ты ведь не забыл про наследования?!
    Я не очень люблю нагромождать свой код зависимостями, а потом постоянно ломать голову мыслями "А от чего у меня унаследован вот этот класс? От какого именно класса у меня унаследован этот метод? Почему одно наследование перекрывает другое? "

    Поэтому я реализовал возможность выборочно унаследовать необходимый метод у конкретного класса, так как такой способ наследования тупо проще, понятнее, и лишний раз не нагружает разум программиста адскими зависимостями между классами.
    Простой пример:



    local Class = require("class")
    
    -- Класс для точки в 2д пространстве
    local Point2d, Point2d_prototype = Class({
        __init__ = function(self, x, y)
            self.x, self.y = x, y
        end,
        printCoords = function(self)
            print("X = ".. self.x .."; Y = ".. self.y)
        end
    })
    
    
    local Player = Class({
        __init__ = function(self, x, y, ...)
            self.x, self.y = x, y
            
            self.otherInfo = ...
        end,
        
        -- Унаследуем метод "printCoords" у класса Point2d
        -- Для этого обратимся к *прототипу* этого метода и получим наследуемый метод по имени
        printCoords = Point2d_prototype.printCoords
    })
    
    -- Создание экземпляра класса Point2d
    local point = Point2d(5, 11)
    -- Вызов метода
    point.printCoords() -- Выведет "X = 5; Y = 11"
    
    
    local player = Player(4, 2, "RccHD")
    player.printCoords() -- Выведет "X = 4; Y = 2"
    

    Исходники библиотеки

     

    Библиотека получилась совсем небольшой, поэтому вы можете скопировать исходник прямо из этой статьи:
    Либо скачать с pastebin ( https://pastebin.com/WVxaHb4Y )
    class.lua :


    local prepareObj
    prepareObj = function(root, obj, proto, mt)
        for k, v in pairs(proto) do
            local t = type(v)
            if t == "table" and k ~= "__proto__" and k ~= "__root__" then
                obj[k] = prepareObj(root, { __proto__ = v, __root__ = root }, v, mt)
            end
        end
        setmetatable(obj, mt)
        return obj
    end
    local classMt = {
        __index = function(self, key)
            local v = self.__proto__[key]
            if type(v) == "function"
            then return function(...) return v(self.__root__, ...) end
            else return v end
        end
    }
    return function(proto)
        proto.__new__ = function(...)
            local obj = { __proto__ = proto }
            obj.__root__ = prepareObj(obj, obj, proto, classMt)
            if proto.__init__ ~= nil then proto.__init__(obj.__root__, ...) end
            return obj
        end
        return proto.__new__, proto
    end
    

    Для того, чтобы начать использовать классы в своих программах нужно положить файл class.lua в папку рядом со своими программами (или в /usr/lib , но лучше не надо)
    После этого импортируйте библиотеку написав в своем коде вот это:


    local Class = require("class")

    И помните: важно не количество кода, а его качество!

    • Нравится 3

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

    Есть ли для этого какой-то блок-детектор в аддонах?


  3. @@RccHD, транспозер и подобные механизмы не могут взаимодействовать с системником? 

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


  4. Раннее я уже делал обзор того, как можно пересылать данные по сундуку из EnderStorage
    Получилось неплохо: 12 байт в секунду
    Но в какой-то момент стало понятно, что 12 байт в секунду - это очень маленькая скорость передачи, поэтому я решил попробовать увеличить это значение

    И у меня получилось! Теперь ender-net передает данные в 42666 раз быстрее(на самом деле можно увеличить скорость передачи до космических значений, можно сделать в 42666*27 раз быстрее, но мне лень). Неплохая прибавка к скорости, я считаю!

    Я бы уже давно реализовал систему именно с такой скоростью передачи данных, если бы я мог видеть очевидные вещи сразу.
    А очевидная вещь вот какая: зачем кодировать данные стаками блоков если есть ДИСКЕТЫ!!! Это настолько очевидно! Дискеты вмещают 512КБ данных, поэтому я решил использовать их для отправки сообщений.

    В обновленной версии ender-net теперь понадобится дисковод для считывания данных

    Вот так выглядит комп, подключенный к сети(при подключении к сети дискета обязательно должна быть вставлена в дисковод)

    9cN17xy.png





    Вот так выглядят компы, подключенные к одной сети

    1DRyiA3.png


     

    *ДЕМКА*

    В настоящий момент система с багами и вообще еще не доработана. Может быть потом выложу ссылку на доработанную библиотеку в комменты.

    Я написал демо-скрипт test-ender-net.lua, который осуществляет пересылку сообщений между участниками сети.

    Пусть у нас есть 3 компа:

    1DRyiA3.png



    Запустим на одном из них скрипт test-ender-net.lua
    rpDwfix.png

    Сеть определила адрес КОМПА -- 4

    Теперь пойдем к другим двум компам и на каждом запустим этот же  скрипт.
    Для двух других компов выбраны адреса 6 и 8

    Пойдем к компу 4 и напишем с этого компа сообщение на комп 8
    EOGc2Lp.png

     

    Потом пойдем к компу 6 и тоже что-нибудь напишем компу под номером 8 (пикчи нет)

    Теперь пойдем к компу номер 8 и ответим компу номер 6 "хватит спамить!"

    je9bz8g.png

     

    Если подойти к компу номер 6, будет видно что пришло сообщение
    owoAVPE.png

     

    Получилось что-то вроде чатика.

     

    Вот в общем-то и все. Если кого-то заинтересовала эта тема, то я могу постараться допилить библиотеку ender-net чтобы не было никаких багов в работе сети.


    Чтобы поближе посмотреть, как работает ender-net через дискеты, скачайте мое сохранение с компами и потестите. (Я там пару подсказок оставил на экранах мониторов). Нужно распокавать архив и положить папку "comp" в папку с сохранениями игры
    Ссылка
    https://www.dropbox.com/s/0h1kc0dhc6vew78/comp.zip?dl=0

    Ссылки на библиотеки и другие скрипты не буду выкладывать, пока не доработаю ender-net



    ИТОГИ

    Главное отличие ender-net от сети на связанных картах: возможность соединить в одну сеть более чем 2 компа.
    Преимущества: почти не тратит энергию, очень быстрая скорость передачи данных.
    Недостатки: возможны баги
    Забавная особенность: при частом обмене сообщениями дисковод издает просто дьявольские звуки, транспозер пищит, а комп мигает! :)

     

    • Нравится 5

  5. Трудности появятся при масштабировании производства.Гораздо чаще возникает ситуация, когда 15 датчиков посылают данные на один пульт. И в этом случае твоя схема увеличивается в 15 раз. Каждый новый датчик потребует для себя постройки не только передатчика с сундуком, но и приемника в каждой точке приема. В результате твоя система обмена данными будет занимать места больше, чем обслуживаемые ею механизмы. Настройка такой системы тоже отнимет много времени.

     

    Вот и нет. Ты видимо неправильно понял устройство моей сети.

    Потому что на самом деле не нужно ставить 15 приемников в точке приема. Достаточно в каждой точке сети поставить ОДИН комп + 1 сундук. А все потому что любой участник сети может и принимать и отправлять сообщения одновременно.

     

    Если два участника вызвали функцию отправки запроса одновременно, то они встанут в очередь, это я продумал


  6.  

    Берем несколько сундуков, закладываем в них 255 разных ресурсов.

    Для передачи информации, переносим ресурсы в эндерчест, по заранее созданной таблице соответствий (синхронизировать можно при старте).

    Получаем 53 байта за раз, следовательно, можно жать информацию, бить на блоки по 53 байта и передавать без особых извращений.

    изначально так и хотел делать, но потом понял что сложно это и решил для начала сделать вариант попроще и постабильнее


  7. А практическая значимость всего этого действа есть или все в ОС это FUN?  :blink:

    Практическая значимость есть...

    Если нужно разослать "легкую" информацию по 15 точкам на огромном удалении друг от друга можно выбрать один из двух вариантов:

     

    1) Обеспечить к каждой точке приток большого кол-ва EU + скрафтить к каждой точке по паре связанных сетевых карт(для которых как раз и была подведена EU).

    Плюс ко всему надо будет писать софт для пересылки сообщения между несвязанными между собой картами. Сеть получится централизированная.

    Задача решена

     

    2) Либо можно установить на каждый комп ender-net + 1 генератор на угле. Задача тоже решена.

    Итог:

    A) меньше заморочек с получением EU.

    B) получилась нецентрализированная сеть, и если у кого-то в сети сломается комп(не важно у кого), то сеть не перестанет функционировать


  8. Вот то же самое хотел посоветовать. Это позволит передавать с максимальной скоростью и даёт 100% шанс, что сообщение было получено, что очень важно. 

    Изначально я реализовывал обмен сообщениями по ender-net в виде broadcast-рассылки. При рассылках обычно не определяют дошло письмо или нет, так как кто-то просто рассылает, и его не волнует успел кто-то прочитать посланное сообщение или нет. 

     

    Но вот как нам определить что сообщение было получено если в нашей ender-сети 15 участников? Выделить 15 слотов под это дело? Или делать инкрементный счетчик от 0 до 14? А что делать если кусок сети просто отвалился и не реагирует?

    Я все это пишу к тому, что рассылать сообщения по принципу broadcast гораздо проще, и тогда не важно кто прочитал, а кто нет. Если кто-то не успевает читать сообщения, пусть увеличивает TPS в своей зоне, убирает бесполезных мобов с территории, либо договаривается об увеличении TIMEOUT'а

     

    Плюс ко всему на основе ender-net можно городить свои протоколы и способы обмена информацией: можно сделать подтверждение о том, что сообщение было получено в виде ответного ender_net.sendMessage, в качестве кода сообщения указать 50(код, который означает что сообщение дошло до получателя), а в качестве самого сообщения указать ID сообщения, которое было получено


  9. Для тех, кому лень искать все ссылки на файлы:

    Библиотека ender-net:
    pastebin get qYiQWtb0 /lib/ender-net.lua

    Простой 'слушатель' сообщений сети
    https://pastebin.com/x6GyEynm

    Драйвер передачи файлов

    base64(необходимая библиотека) - pastebin get 0xDgW35R /lib/ender-net-base64.lua

    Драйвер состоит из двух программ
    1) waitFile.lua (установить можно командой pastebin get aD20ZF4q /bin/waitFile.lua)
    2) sendFile.lua (установить можно командой pastebin get wHA6QzH6 /bin/sendFile.lua)


  10.  

     


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

    Связанные карты нельзя связать в целостную сеть без серверных стоек(или роутеров) и без написания доп. кода к ним
    Представь ситуацию, когда информация о температуре реактора должна рассылаться в 15 точек одновременно.
    В таком случае нам понадобится аж 30 связанных карт + придется потратить энергии на 15 запросов(а они у связанных карт недешевые в плане энергии). А ведь нам всего лишь нужно переслать одно жалкое число и ничего более

    Вот чтобы не тратиться на сетевые карты и не обеспечивать к каждому компу сети большое кол-во энергии, можно использовать ender-net

    Я конечно не спорю, что связанные карты удобнее, но для таких мелочных операций как пересылка чисел более чем одному получателю они не совсем подходят. В таких случаях я бы предпочел ender-net
×
×
  • Создать...