Darkar25
-
Публикации
39 -
Зарегистрирован
-
Посещение
-
Победитель дней
2
Сообщения, опубликованные пользователем Darkar25
-
-
Пофиксил геоанализатор, Добавил недостающие проверки в классе агента, Добавил метод для получения направления взгляда робота без улучшения "Навигация"...
UPD спустя 4 часа:
Нашел на форуме парочку очень интересных тем: фильтрация шума геоанализатора и вычисление константы шума геоанализатора...добавил соответствующие методы в код сервера
Тема с получением шумовой константы
UPD спустя 2 часа:
Добил документацию во всех важных точках кода.можно сказать с доками покончено(естественно в будущем будут добавляться новые методы а с ними и новые доки, но на данный момент код полностью задокументирован)
-
2
-
-
2 часа назад, num_pi сказал:Ты имеешь ввиду, что, что бы отправить данные формат которых это таблица, её надо конвертировать в строку? И спрашиваешь как это сделать, лучшим образом, я правильно понимаю?
Верно. есть в луа таблица (table) и её надо в какой-нибудь формат перевести чтобы можно было перегнать с машины(компьютер/робот в майнкрафте) по сокету на сервер и там прочитать данные...на данный момент я эту проблему решил выдернув json енкодер с гитхаба и переделав его под свои нужды...если есть решение получше то хотелось бы его зачитать и возможно применить в этом проекте...
-
@num_pi, порылся в инете и выяснил что луа из коробки не умеет конвертировать таблицы в строки (ну разве что table.concat или string.pack, но они подходят только для очень простых случаев, а для передачи например информации о результате сканирования геоанализатором нужно передавать таблицу полностью, вместе с подтаблицами)...и учитывая что на шарпе нет адекватных парсеров луа таблиц подходящих под методы конвертации рекомендуемые в интернете то за неимением альтернатив - json остаётся основным способом передачи данных с машины на сервер...чутка енкодер на клиенте покромсал(теперь он по кол-ву строк даже меньше основного кода клиента), использовал более правильные техники работы с таблицами и конкатенации строк и по идее он стал побыстрее чем до этого...
Но если есть предложения как всё-таки избавить клиент от необходимости как-то обрабатывать таблицы лишний раз перед отправкой то буду рад выслушать
-
Добавил глобальное кэширование и методы для получения уровня некоторых компонентов
UPD спустя 7 часов:
Пофиксил смешивание пакетов (это всетаки был серверный косяк а не клиентский) и теперь можно спокойно зашвыривать машину пакетами и ничего от этого не будет
Добавил поддержку Inf и NaN на приём от машины
Сделал метод Invoke чуть более умным, теперь не нужно экранировать строки при подаче их в этот метод, он сделает это сам...так-же добавил пачку захардкоженных типов переменных для преобразования...
Добавил алиасы для енума Sides, отключаются директивой предпродессора OpenOS
-
По просьбе @ECS добавил метод GetComponents() для получения списка компонентов асинхронно...
Так-же добавил(хотя лучше сказать тупо скопипастил с вики опенкомпов) в код документацию, правда пока что только для компонентов...
-
1
-
-
3 минуты назад, num_pi сказал:если избавится от json и на клиенты слать сразу lua table, можно увеличить скорость обработки данных в разы.
Прости, не совсем тебя понял...на клиенты json не шлётся...json шлётся только от клиента к серверу как ответ на команду но не наоборот...или ты предлагаешь слать lua table как ответ серверу?в таком случае согласен, можно спокойно убирать огромный json.encode и на сервере сделать какой-нибудь парсер для этого добра...может быть даже сделаю так...скорее всего с ходу оно не начнет работать и придётся чуть-чуть поправить код сервера под новую структуру данных но в остальном предложение довольно дельное...
-
3 часа назад, ECS сказал:или как минимум текстовые summary с пояснением, что вот этот метод асинхронен, а этот нет:
summary я напишу везде, оно у меня в планах уже есть...summary бывают довольно полезны когда непонятно что вообще за метод в чужом коде и надо по-быстрому разобраться...просто навёл мышку и вот тебе пояснения...
-
9 минут назад, ECS сказал:А список запрашивается часом не синхронно? Что произойдёт, если, к примеру, я в мгновение обращусь к свойству machine.Components у 50 подключённых машин? Заблокируется ли серверный поток вплоть до получения всех списков? Если да, то было бы неплохо получать компоненты через await machine.GetComponents() без фризов
Запрашивается синхронно..идея с методом хорошая, обязательно добавлю)
9 минут назад, ECS сказал:Вообще согласен, особенно если сервер не имеет синхронных методов - в этом случае суффиксы Async бессмысленны. Но тут он имеет!11
Ну по факту из синхронных аналогов методов там только свойства, половину из которых юзать вообще ни разу не хорошая идея и лучше вообще выключить в свойствах проекта)))
Ну вообщем окей, может быть протыкаю Async на всех методах в будущем...
-
1
-
-
9 минут назад, ECS сказал:А в целом было бы очень клёво иметь нейминг по конвенциям майков или как минимум текстовые summary с пояснением, что вот этот метод асинхронен, а этот нет
Ну...по-хорошему стоит так сделать, да...но учитывая что почти все методы в компонентах асинхронные то можно привыкнуть и Async на концах методов будет только лишним удлиннением имени...да и визуал студия лепит варнинг если асинхронный метод используется без await так что случайно неправильно заюзать асинхронный метод будет довольно трудно...
-
28 минут назад, ECS сказал:почему некоторые методы машины синхронны (components.TryGet), а другие асинхронны (gpu.Bind), если и тот, и другой выполняются на одной синхронной машине? В случае с Bind я асинхронно ожидаю результат привязки, это логично. А почему тогда список компонентов возвращается синхронно?
Сам список компонентов синхронный потому, что он запрашивается всего один раз при первом обращении к свойству списка компонентов и его не нужно постоянно по новой запрашивать с машины - все компоненты уже есть на сервере...ну и по мере необходимости ловится сигнал добавления\удаления компонентов, это тоже не требует слать команды на машину...поэтому собственно список компонентов и синхронный в отличие от методов самих компонентов которые шлют команды на машину и ожидают от неё ответа...
-
Что такое RemoteOS
RemoteOS - это мост для связи OpenComputers с внешним миром, написанный на языке C# (.NET 6.0).
В чём отличие RemoteOS от уже существующих решений
- Начнём с самого очевидного и главного - на сервере имеется (почти) точная копия API OpenComputers. Это позволяет не только использовать подсказки в коде при работе с мостом в IDE но и проверять данные подаваемые в методы ещё до отправки их на компьютер OpenComputers(далее машина). Так-же такой подход позволяет реализовать кэширование, которое даёт возможность в некоторых местах не дёргать постоянно машину для опроса актуальных значений...
- Из-за того что на сервере наклёпано столько архитектуры он не такой легковесный как остальные мосты...
- Мой мост работает не из под OpenOS а прямо с EEPROM'а, что позволяет значительно снизить минимальные системные требования для работы этого моста но при этом это же отличие значительно его ограничивает - будут недоступны все те удобненькие библиотеки из опенос, то-есть нельзя работать ни с чем кроме того что предоставляет lua и клиентская ос моста...
- Не нужно запрашивать сигналы с машины, она сама их шлёт серверу...
Какие у RemoteOS системные требования
Для машины - интернет карта и EEPROM прошитый на клиентскую ос RemoteOS
Скрытый текстКомпьютер:
(Компьютеры могут иметь интернет-платы только со 2 уровня)
Микроконтроллер:
(Микроконтроллеры могут иметь интернет-платы только со 2 уровня)
Дрон:
Планшет:
Для сервера - 1 открытый сетевой порт чтобы иметь связь с машиной и достаточная вычислительная мощность чтобы суметь запуститься а затем отсылать пакеты машинам, получать от них ответ и обрабатывать этот ответ...
Как же всё таки пользоваться RemoteOS
Начнём с того что C# - не самый удачный выбор для связки с LUA ибо C# это строго типизированный яп а луа не очень...и подгонять сервер под все причуды луа кода было тем ещё приключением...но у меня вроде как вышло, так что посмотрим как всем этим добром пользоваться...
Ловля подключений:
Скрытый текстСамый простой сервер выглядит как-то вот так...
var server = new RemoteOSServer(IPAddress.Any, 4466); server.onConnected += async (Machine machine) => { //machine - наша только что подключившаяся машина, большинство дальнейших туториалов будут подразумевать что вы пишете код внутри этого блока }; server.Start(); Console.WriteLine("Server started"); while(true) Thread.Sleep(0);
Компоненты:
Скрытый текстНачало работы с любым компонентом лежит через метод GetComponents в нашей машине...желательно вынести результат этого метода в отдельную переменную, чтобы не удлиннять код лишний раз
var components = await machine.GetComponents();
Список компонентов содержит несколько основных методов для работы с списком компонентов...
components.IsAvailable<RobotComponent>() //Проверяет, есть ли такой компонент в машине components.List<ScreenComponent>() //Получает список всех компонентов указанного типа components.GetPrimary<Printer3DComponent>() //Получает компонент указанного типа, если такого компонента нет возвращает null components.TryGet<KeyboardComponent>(out var keyboard) //Расширение RemoteOS, добавляющее Try метод для получения компонентов - это как IsAvailable и GetPrimary в одном методе
После того как компонент получен, можно использовать его функционал, например привязать экран к видеокарте и написать какой-нибудь текст
if(components.TryGet<ScreenComponent>(out var screen) && components.TryGet<GraphicsCardComponent>(out var gpu)) { if(await gpu.Bind(screen)) { await gpu.Set(1, 1, "Hello from RemoteOS!"); } }
Все методы всех компонентов я тут перечислять не буду иначе пост будет занимать 3 километра чистого текста

Лучше сами разверните сервер и потыкайтесь...Следующие компоненты НЕ ПОДДЕРЖИВАЮТСЯ в RemoteOS:
- Debug карта (реализация довольно сложная, решил забить)
- Редстоун карты
- Улучшение торговли
- Интернет карта (зачем интернет на машине если есть интернет на сервере)
- Дата-карта 3 уровня (зачем криптография на машине если есть криптография на сервере)
Но вы всегда можете либо добить совместимость существующих компонентов либо добавить свои собственные...вот пример тестового компонента:
[Component("test")] //в кавычках пишется имя компонента в OpenComputers, если этого аттрибута нет то компонент не будет обрабатываться сервером - это может быть полезно для налседования компонентов public partial class MyComponent : Component //Необходимо наследоваться от Component { public MyComponent(Machine parent, Guid address) : base(parent, address) { } public async Task MySetter(int somevalue, string val) => await Invoke("setSomething", somevalue, val); //вызываем метод Invoke чтобы запустить метод на машине от имени этого компонента public async Task<int> MyGetter() => (await Invoke("getSomething"))[0]; // С недавних пор компоненты поддерживают автоматическое вычисление имени метода для вызова на машине // Для этого используется метод GetInvoker который возвращает делегат, в который можно передать все необходимые аргументы метода. public async Task MyInvokerMethod(int somevalue, string val) => await GetInvoker()(somevalue, val); // Вызовет метод myInvokerMethod на машине // Так-же можно не реализовывать метод самому и предоставить это генератору // Сгенерированный метод будет просто вызывать соответствующий метод на удалённой машине. public partial Task<string> PartialCall(); // Сгенерированный код: => (await GetInvoker()())[0]; // Для методов без результата генератор не будет использовать async/await // Аргументы тоже поддерживаются генератором public partial Task AnotherPartialCall(string somevalue); // Сгенерированный код: => GetInvoker()(somevalue); }
Следующие компоненты поддерживаются, но НЕ РЕКОМЕНДУЮТСЯ:
- Компонент базы данных (лучше хранить информацию о предметах на сервере)
- Дата-карты 1 и 2 уровня (весь функционал этих карт отлично выполняется и на сервере, входные данные не проверяются на правильность)
- Диски (лучше хранить все свои файлы на сервере, как минимум потому что на сервере намного больше места)
- EEPROM (по той-же причине что и 3 пункт)
- Файловые системы (по той-же причине что и 3 пункт)
Сигналы:
Скрытый текстНесмотря на то, что pullSignal и pushSignal полностью поддерживаются в RemoteOS их крайне не рекомендуется использовать...вместо этого лучше работать с сигналами на сервере без лишнего дёргания машины...вот парочка примеров:
//Компоненты могут реализовывать свои ивенты на которые можно подписаться и слушать всякие интересные штуки...вот например нажатия на клавиши на клавиатуре на машине if ((await machine.GetComponents()).TryGet<KeyboardComponent>(out var keyboard)) { keyboard.KeyDown += async (c, key, player) => //Конкретно этот ивент передает char, код клавиши и имя игрока нажавшего клавишу...компоненты могут реализовывать свои ивенты со своими наборами данных { Console.WriteLine($"{player} нажал кнопку '{c}' ({key})"); }; } //Можно использовать и более низкоуровневый способ слушать ивенты machine.Listen("inventory_changed", (parameters) => { Console.WriteLine("У робота поменялся инвентарь в слоте: " + parameters[0]); }); //Так-же можно отсылать и принимать кастомные сигналы machine.Listen("remoteos_test", (data) => { Console.WriteLine("Тестовый сигнал с данными: " + string.Join(",", data.Linq.Select(x => x.Value))); }); machine.FireSignal("remoteos_test", 1, 234, "asd", true); //Да, можно и через machine.Computer.PushSignal("remoteos_test", 1, 234, "asd", true) но зачем...так же намного шустрее реагирует...
Выполнение произвольного кода:
Скрытый текстТут тоже ничего трудного нет, просто используем Execute или RawExecute
machine.Execute("computer.beep(1000, 1)"); //Выполнится код return json.encode({computer.beep(1000, 1)}) machine.RawExecute("computer.beep(1000, 1)"); //То-же самое что и метод выше но без обёртки в json.encode и без return
Директивы предпроцессора:
Скрытый текстПроект RemoteOS содержит несколько настраиваемых переменных
ROS_PROPERTIES - Добавляются свойства для повышения читабельности вашего кода
ROS_PROPS_UNCACHED - Добавляются некэшируемые свойства, их добавлять не рекомендуется так-так свойства не асинхронные и множественный вызов некэшируемых свойств может значительно понизить скорость работы сервера
ROS_GLOBAL_CACHING - Сервер использует глобальное кэширование для снижения количества вызовов методов на машине, сохраняя некоторые свойства компонентов для восстановления этих свойств при обращении к ним на компонентах того-же типа
OpenOS - Добавляются расширения для компонентов аналогичные расширениям OpenOS
В файле Helpers/OpenOS.cs в самом начале файла так-же можно настроить конкретные категории расширений
В файле Helpers/RemoteOSExtensions.cs в самом начале файла можно настроить категории расширений от RemoteOS
Веб сервер:
Скрытый текстНа данный момент веб сервер имеет довольно скудный функционал - только бегать роботами по карте и сканировать всё вокруг.
На сайте имеется Waila, дебаг информация (F4), полноценный рендер блоков.
Для начала работы с сайтом нужно запустить веб сервер и подключить к нему одного или более роботов/компьютеров/дронов(тестировалось только на роботах, но в теории должно работать исправно и с остальными типами машин).
После того как робот подключился к серверу он появится в списке машин слева сверху и будет иметь один из нескольких статусов:
OFFLINE - машина оффлайн, управлять ей сейчас нельзя. в этом статусе можно только изменять координаты машины.
AWAITING POSITION - эта машина впервые подключилась к серверу и необходимо установить координаты нажав на эту кнопку
READY - машина онлайн и готова к управлению. при нажатии на эту кнопку машина перейдёт в статус SELECTED
SELECTED - текущая выделенная машина которой вы сейчас управляете
После того как вы выбрали робота вы можете управлять им используя кнопки WASD, Shift(опуститься вниз), Space(подняться наверх).
Управление камерой:
ЛКМ - Вращать камеру
ПКМ - Перемещать камеру
СКМ - Приблизить/Отдалить
На сайте установлены такие "моды" как minecraft, opencomputers, wailaharvestability, remoteos(модельки для роботов и дронов). чтобы установить дополнительные моды необходимо закинуть в папку wwwroot/assets необходимые ассеты(текстуры, модели, файлы локализации). я постарался сделать так, чтобы сайт требовал минимального вмешательства в ассеты для установки, но к сожалению иногда приходится делать мапперы для файлов локализаций и менять модели чтобы они корректно загружались на сайте.
Скриншот сайта:
Какие у меня планы на RemoteOS- [+] Планирую добавить документацию в код, чтобы можно было прямо в IDE зачитать что конкретный метод делает...
- [+] Хочу сделать веб-интерфейс для управления машинами
- Хочу довести кэширование до ума, чтобы надо было дёргать машины ещё меньше
- Может быть добавлю поддержку локальной(внутриигровой) сети на сетевых картах/ретрансляторах чтобы ещё больше снизить минимальные требования для клиентской ос
Ссылки
Репозиторий проекта: Тык (Github)
Клиентская ОС: Тык (Github)
Демо-видео: Тык (Яндекс диск)
-
6
-
Какой-то несвязный поток мыслей. Отвечу на вопрос, который я понял.
- Создаём на дискете файл .prop, туда пишем {label = "MineOS"} или {label = "MineOS", reboot = true}, если нужно ребутаться.
- Создаём на дискете файл .install, туда пишем os.execute("pastebin run 0nm5b1ju").
- Та-дам.
спасибо...помог..
-
вот в чем вопрос: как сделать дискету установочным диском?к примеру закинул ты туда установщик MineOS(0nm5b1ju) и хочешь чтобы на другом компе при написании в shell Install запускался установщик MineOS.как это можно реализовать?
т.к при написании pastebin run 0nm5b1ju докачиваются дополнительные файлы то нужно чтобы запускался не установщик а выполнялась команда(в нашем случае pastebin run 0nm5b1ju) и как сделать так чтобы при открывании какого либо файла в формате lua в shell посылалась команда?
-
т.к. в кодинге на луа я больше рак чем 5 крабов вместе взятых попрошу у вас помощи написать мне прогу для отладочной карты(представим у меня есть такая плата и она у меня вшита в планшет)...как можно сделать так чтобы при нажатии определенных кнопок происходило соотвествующее им десвие(к примеру нажал G и выполнилась команда setGameType(value: string) с которой я сам еще не разобрался...или при нажатии 1 выполнялась команда getposition() number, number, number и запоминались координаты потом при нажатии 2 также запоминались вторые координаты(как выделение в WE) и потом при нажатии S выводилось окно в которое надо написать айди блока который при нажатии enter сетнется как в WE) и так далее...и если такая программа есть то подскажите её и не мучайте себя))если же нет то помогите склепать
-
1
-
-
-
подскажите какие есть команды для отладочной карты пжлст...
-
А у тебя вайфай-точки поблизости нет?
ну...а точка доступа у которой нет питания от энергии считается?
-
я модернезировал прогу для управления роботом с планшета...и в связи с недавними изменениями(добавлением возможности копать перед роботом и возможностью копать в 3 стороны(вперед наверх и вниз))после отправки команды роботу он выполняет её дважды
помогите пж...
ПЛАНШЕТ - https://pastebin.com/cMcYEQAW
РОБОТ - https://pastebin.com/4mDUTWKN -
ошибку решил код полностью работоспособен...
-
Просто куда-то затерялась переменная 'slot', если ее вернуть, то никаких ошибок. А нужные функции, без проблем добавляются в таблицу 'commands'.
я скорее всего понял в чем ошибка...нужно чтобы переменная slot задавалась изначально...тогда никаких ошибок не будет...я пока сам попробую это сделать и напишите как это можно сделать если у меня не выйдет
-
local component = require("component") local robot = require("robot") local event = require("event") local port = 512 local modem if component.isAvailable("modem") then modem = component.modem else error("Этой программе требуется беспроводной модем для работы!") end modem.open(port) local commands = { forward = robot.forward, back = robot.back, turnRight = robot.turnRight, turnLeft = robot.turnLeft, up = robot.up, down = robot.down, suck = robot.suck, drop = function() -- создаем функцию дропа robot.drop() -- дропаем предмет вперед slot = (slot + 1)%robot.inventorySize() -- задаем номер следующего if slot == 0 then -- проверяем исключение slot = 1 -- назначаем, в случае исключения end robot.select(slot) -- выбираем end, } local function receive() while true do local e = {event.pull('modem_message')} if commands[e[7]] then -- если в списке есть такая команда commands[e[7]]() -- выполнить end end end receive()как я и говорил выпиливанеи кучи строк урежет кучу возможностей...теперь он не может экстренно стереть все данные с робота,испустить редстоун сигнал вокруг робота...и при попытке выкинуть предмет выдает ошибку при этом предмет бросается
-
recieve.lua:92: <eof> expected near 'end'
щао?как это исправить?
я понимаю что чтото связаное с 92 строкой с концом чегото...но чего? -
заменить 'cmd' на 'commands' в строках 59, 60 и удалить все с 61 до 87
ну и поправить event.pull() на event.pull('modem_message')
а...зачем собсна удалять такую тучу строк?ну...я особо не разбираюсь но наверно это много функций порежет...
-
заменить 'cmd' на 'commands' в строках 59, 60 и удалить все с 61 до 87
ну и поправить event.pull() на event.pull('modem_message')
сейчас проверю

RemoteOS - C# мост
в За пределами Minecraft
Опубликовано:
Решил возобновить разработку спустя год)
Добавил веб интерфейс для управления машинами, сделал source генератор для компонентов, переписал некоторые методы в компонентах с туплов на OneOf, чутка поменял расположение некоторых файлов в проекте, пофиксил некоторые косяки в компонентах которые не заметил при написании компонентов...
Первое сообщение в теме обновил доп.инструкциями для новых фишек