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

Рекомендуемые сообщения

Что такое RemoteOS

RemoteOS - это мост для связи OpenComputers с внешним миром, написанный на языке C# (.NET 6.0).

В чём отличие RemoteOS от уже существующих решений

  • Начнём с самого очевидного и главного - на сервере имеется (почти) точная копия API OpenComputers. Это позволяет не только использовать подсказки в коде при работе с мостом в IDE но и проверять данные подаваемые в методы ещё до отправки их на компьютер OpenComputers(далее машина). Так-же такой подход позволяет реализовать кэширование, которое даёт возможность в некоторых местах не дёргать постоянно машину для опроса актуальных значений...
  • Из-за того что на сервере наклёпано столько архитектуры он не такой легковесный как остальные мосты...
  • Мой мост работает не из под OpenOS а прямо с EEPROM'а, что позволяет значительно снизить минимальные системные требования для работы этого моста но при этом это же отличие значительно его ограничивает - будут недоступны все те удобненькие библиотеки из опенос, то-есть нельзя работать ни с чем кроме того что предоставляет lua и клиентская ос моста...
  • Не нужно запрашивать сигналы с машины, она сама их шлёт серверу...

Какие у RemoteOS системные требования

Для машины - интернет карта и EEPROM прошитый на клиентскую ос RemoteOS

Скрытый текст

Компьютер:Screenshot_1220.png.da75482f563746bbe26de2e244ba50c3.png (Компьютеры могут иметь интернет-платы только со 2 уровня)

Микроконтроллер: Screenshot_1197.png.d0e4bf676f006e469592a510eafc3f96.png (Микроконтроллеры могут иметь интернет-платы только со 2 уровня)

Дрон: Screenshot_1203.png.9688b7026f9e45ae4444e68db8af2a93.png

Планшет: Screenshot_1211.png.6bdaeea8a5b6c6dfea92139c09754f91.png

Для сервера - 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:

  1. Debug карта (реализация довольно сложная, решил забить)
  2. Редстоун карты
  3. Улучшение торговли
  4. Интернет карта (зачем интернет на машине если есть интернет на сервере)
  5. Дата-карта 3 уровня (зачем криптография на машине если есть криптография на сервере)

Но вы всегда можете либо добить совместимость существующих компонентов либо добавить свои собственные...вот пример тестового компонента:


[Component("test")] //в кавычках пишется имя компонента в OpenComputers, если этого аттрибута нет то компонент не будет обрабатываться сервером - это может быть полезно для налседования компонентов
public class MyComponent : Component //Необходимо наследоваться от Component
{
	public MyComponent(Machine parent, Guid address) : base(parent, address)
	{
	}

	public async Task<int> MyGetter() => (await Invoke("getSomething"))[0]; //вызываем метод Invoke чтобы запустить метод на машине от имени этого компонента
	public async Task MySetter(int somevalue, string val) => await Invoke("setSomething", somevalue, val);
}

Следующие компоненты поддерживаются, но НЕ РЕКОМЕНДУЮТСЯ:

  1. Компонент базы данных (лучше хранить информацию о предметах на сервере)
  2. Дата-карты 1 и 2 уровня (весь функционал этих карт отлично выполняется и на сервере, входные данные не проверяются на правильность)
  3. Диски (лучше хранить все свои файлы на сервере, как минимум потому что на сервере намного больше места)
  4. EEPROM (по той-же причине что и 3 пункт)
  5. Файловые системы (по той-же причине что и 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

В файле OpenOS.cs в самом начале файла так-же можно настроить конкретные категории расширений

В файле RemoteOS.cs в самом начале файла можно настроить категории расширений от RemoteOS

 

Какие у меня планы на RemoteOS

  • [+] Планирую добавить документацию в код, чтобы можно было прямо в IDE зачитать что конкретный метод делает...
  • Хочу сделать веб-интерфейс для управления машинами
  • Хочу довести кэширование до ума, чтобы надо было дёргать машины ещё меньше))
  • Возможно сделаю свой LINQ провайдер, чтобы можно было цеплять несколько методов в один запрос без особых усилий...думаю это уменьшит время отклика машины в некоторых случаях...
  • Возможно добавлю какое-то подобие adhoc или меш сети чтобы ещё больше занизить планку минимальных требований...эта сеть должна будет работать на обычных беспроводных карточках 1 уровня и машины смогут перекидывать по внутренней сети пакеты от машин с интернет картой их получателям и потом возвращать их обратно чтобы машина с интернет картой отправила ответ обратно на сервер...эта задача довольно трудная, не уверен смогу ли её реализовать и целесообразна ли она вообще так как это значительно увеличит время отклика и повысит траффик на входных\выходных точках сети что тоже может стать проблемой... Отбой, новая идея: если рестрансляторы это то, что я думаю то это идеальный вариант - не надо будет делать сложную прогу с автоперестройкой марштрутов сети и при этом они легко крафтятся, можно будет просто натыкать кучку ретрансляторов по всей необходмой площади покрытия и готово...останется только приспособить клиентскую ос под простой отсыл и приём пакетов с беспроводной карточки...

Ссылки

Репозиторий проекта: Тык (Github)

Клиентская ОС: Тык (Github)

Демо-видео: Тык (Яндекс диск)

Изменено пользователем Darkar25

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Затестил, очень интересная и довольно удобная реализация, особенно понравилась подписка на ивенты компонентов. Хотя есть вопрос, не дающий покоя: почему некоторые методы машины синхронны (components.TryGet), а другие асинхронны (gpu.Bind), если и тот, и другой выполняются на одной синхронной машине? В случае с Bind я асинхронно ожидаю результат привязки, это логично. А почему тогда список компонентов возвращается синхронно? А в целом было бы очень клёво иметь нейминг по конвенциям майков или как минимум текстовые summary с пояснением, что вот этот метод асинхронен, а этот нет:

 

image.png.d8f562faec762018314c7997125dfb74.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
28 минут назад, ECS сказал:

почему некоторые методы машины синхронны (components.TryGet), а другие асинхронны (gpu.Bind), если и тот, и другой выполняются на одной синхронной машине? В случае с Bind я асинхронно ожидаю результат привязки, это логично. А почему тогда список компонентов возвращается синхронно?

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

Изменено пользователем Darkar25

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
9 минут назад, ECS сказал:

А в целом было бы очень клёво иметь нейминг по конвенциям майков или как минимум текстовые summary с пояснением, что вот этот метод асинхронен, а этот нет

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
12 минуты назад, Darkar25 сказал:

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

Выглядит удобно. А список запрашивается часом не синхронно? Что произойдёт, если, к примеру, я в мгновение обращусь к свойству machine.Components у 50 подключённых машин? Заблокируется ли серверный поток вплоть до получения всех списков? Если да, то было бы неплохо получать компоненты через await machine.GetComponents() без фризов

 

15 минут назад, Darkar25 сказал:

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

Вообще согласен, особенно если сервер не имеет синхронных методов - в этом случае суффиксы Async бессмысленны. Но тут он имеет!11

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
9 минут назад, ECS сказал:

А список запрашивается часом не синхронно? Что произойдёт, если, к примеру, я в мгновение обращусь к свойству machine.Components у 50 подключённых машин? Заблокируется ли серверный поток вплоть до получения всех списков? Если да, то было бы неплохо получать компоненты через await machine.GetComponents() без фризов

Запрашивается синхронно..идея с методом хорошая, обязательно добавлю)

 

9 минут назад, ECS сказал:

Вообще согласен, особенно если сервер не имеет синхронных методов - в этом случае суффиксы Async бессмысленны. Но тут он имеет!11

Ну по факту из синхронных аналогов методов там только свойства, половину из которых юзать вообще ни разу не хорошая идея и лучше вообще выключить в свойствах проекта)))

Ну вообщем окей, может быть протыкаю Async на всех методах в будущем...

Изменено пользователем Darkar25

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 часа назад, ECS сказал:

или как минимум текстовые summary с пояснением, что вот этот метод асинхронен, а этот нет:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я может плохо смотрел, но по своему опыту скажу что если избавится от json и на клиенты слать сразу lua table, можно увеличить скорость обработки данных в разы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 минуты назад, num_pi сказал:

если избавится от json и на клиенты слать сразу lua table, можно увеличить скорость обработки данных в разы.

Прости, не совсем тебя понял...на клиенты json не шлётся...json шлётся только от клиента к серверу как ответ на команду но не наоборот...или ты предлагаешь слать lua table как ответ серверу?в таком случае согласен, можно спокойно убирать огромный json.encode и на сервере сделать какой-нибудь парсер для этого добра...может быть даже сделаю так...скорее всего с ходу оно не начнет работать и придётся чуть-чуть поправить код сервера под новую структуру данных но в остальном предложение довольно дельное...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
10 минут назад, Darkar25 сказал:

Прости, не совсем тебя понял...на клиенты json не шлётся...json шлётся только от клиента к серверу как ответ на команду но не наоборот...или ты предлагаешь слать lua table как ответ серверу?в таком случае согласен, можно спокойно убирать огромный json.encode и на сервере сделать какой-нибудь парсер для этого добра...может быть даже сделаю так...скорее всего с ходу оно не начнет работать и придётся чуть-чуть поправить код сервера под новую структуру данных но в остальном предложение довольно дельное...

Да я про это, хоть у тебя и в одну сторону идёт обмен, но всё же. На операцию json.encode тратится много времени, можешь даже кстати замерить с секундомером, у меня прирост в скорости обмена данными, был минимум в два раза, как сейчас помню, было 10-8 секунд, стало 4-3 в зависимости от длинны данных. Я обрабатывал поисковой запрос от магазина, искал по таблице и эту операцию поиска выполнял сервер, а потом отдавал готовую таблицу с данными. Да, знаю что это безумие, но всё же =)
Хоть у тебя идёт только отправка, хотя я в своём магазине ещё и принимал данные в формате json, думаю всё же стоит попробовать убрать json из уравнения обмена данными.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не поленился, и всё же открыл свой git сервер, что бы найти код этого безумия :D

php код серверной части:

function giveItemsListBysearchKeyWord()
{ //функция поиска в списке предметов по ключевому слову. Дальнейшая расфосовка результата по страницам и отдача готового результата клиенту 
    include 'connectTodb.php';

    $ItemsListForClient;
    $giveItemsListToClientArray = null;

    $getJsonDataFromClient = json_decode($_GET['jsonData'], true);
    //var_dump($jsonDataFromClientsDBitems);
    $searchKeyWord =  strval($getJsonDataFromClient['dataFromClient']); //ключевое слово, для поиска по базе данных.
    $selectItemsListBysearchKeyWord = $mysqli->query("SELECT itemLabel, itemDamage, itemName, itemUUID, itemPriceCoins, itemmaxSize, canCraft, itemOnSaleStatus
    FROM items_market WHERE itemOnSaleStatus = 1 and itemLabel like '%$searchKeyWord%'");

    foreach ($selectItemsListBysearchKeyWord as $key => $value) { //Поиск совпадения по ключевому слову из GET запроса, и забивка в новую таблицу, что бы в дальнейшем побить это всё на страницы и строки.
        if (!empty($value)) {
            //var_dump($row);
            $ItemsListForClient[] = array(
                "itemUUID" => $value['itemUUID'],
                "itemDamage" => $value['itemDamage'],
                "itemName" => $value['itemName'],
                "itemLabel" => $value['itemLabel'],
                "itemmaxSize" => $value['itemmaxSize'],
                "canCraft" => $value['canCraft'],
                "itemPriceCoins" => $value['itemPriceCoins']
            );
            //var_dump($ItemsListForClyient);
        }
    }
    if (!empty($ItemsListForClient)) {

        $countallItems = count($ItemsListForClient); //выяснение сколько в общем элементов в массиве  allItems и запись этого результата в переменную
        $countPage = ceil($countallItems / 15); // деление на количество элементов в массие, строк на странице будет 16
        $ArrayWalkStart = 0;
        $ArrayWalkEnd = 15;
        for ($z = 1; $z <= $countPage; $z++) {
            //echo "Z:".$z." "; 
            //giveItemsListToClientArray[] = $z;
            $giveItemsListToClientArray[] = splittItemsListIntoPages($ArrayWalkStart, $ArrayWalkEnd, $ItemsListForClient);
            $ArrayWalkStart = $ArrayWalkStart + 15;
            $ArrayWalkEnd = $ArrayWalkEnd + 15;
        }
        echo json_encode($giveItemsListToClientArray);
        //var_dump($giveItemsListToClientArray);
    } else {
        echo json_encode("searchReturnEmpty"); //это если ни чего не найдено
    }
}

Библа что использовалась на стороне клиента для кодирования и декодирования запрос-ответа. https://github.com/rxi/json.lua/blob/master/json.lua

 

Код на стороне клиента. Да тут кусок, но суть думаю будет ясна. То есть, написал в строке поиска слово, нажал enter, запрос улетел на сервер в json формате, потом принимаю ответ и декодируя json строку, если не пусто, то рисую таблицу с результатом на экран.

    if signal[1] ~= "key_down" and signal[1] == "key_up" and specChar == 28 then --28 это номер клавиши enter
        local response = getRequest(whereSearchMethod,searchSaveTypeInputText)
        if response then
            if response == "searchReturnEmpty" then
                pageNum = 1
                searchReturnEmpty_KeyTouchToRow = 0
                whichTableToUseSwitch = searchReturnEmptyTable --Бьём пустой список предметов.
                tableToUse = whichtableToUse() 
                eventDrawTablePageAndClickRow(pageNum, tableToUse, nil, 1, "itemLabel","itemPriceCoins") --вызов отрисовки страницы
                fill(2,5,78,18, " ", 0x303030) -- цвет фона в itemlist
                set(nil, 12, "Хм, странно, но похоже что ни чего не найдено...", 0x303030, 0xffc107)
                set(nil, 14, "Попробуй поискать что-нибудь другое!", 0x303030, 0xffc107)
            else
                pageNum = 1 
                searchReturnEmpty_KeyTouchToRow = 1
                searchOnServerInItemsList = response
                whichTableToUseSwitch = searchOnServerInItemsList
                tableToUse = whichtableToUse()
                eventDrawTablePageAndClickRow(pageNum, tableToUse, nil, 1, "itemLabel","itemPriceCoins") --вызов отрисовки страницы
            end
        else
            FormOutOfService("Ошибка поиска, сервер не доступен!")
        end
    end

 

Изменено пользователем num_pi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

По просьбе @ECS добавил метод GetComponents() для получения списка компонентов асинхронно...

Так-же добавил(хотя лучше сказать тупо скопипастил с вики опенкомпов) в код документацию, правда пока что только для компонентов...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Добавил глобальное кэширование и методы для получения уровня некоторых компонентов

UPD спустя 7 часов:

Пофиксил смешивание пакетов (это всетаки был серверный косяк а не клиентский) и теперь можно спокойно зашвыривать машину пакетами и ничего от этого не будет :D

Добавил поддержку Inf и NaN на приём от машины

Сделал метод Invoke чуть более умным, теперь не нужно экранировать строки при подаче их в этот метод, он сделает это сам...так-же добавил пачку захардкоженных типов переменных для преобразования...

Добавил алиасы для енума Sides, отключаются директивой предпродессора OpenOS

Изменено пользователем Darkar25

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@num_pi, порылся в инете и выяснил что луа из коробки не умеет конвертировать таблицы в строки (ну разве что table.concat или string.pack, но они подходят только для очень простых случаев, а для передачи например информации о результате сканирования геоанализатором нужно передавать таблицу полностью, вместе с подтаблицами)...и учитывая что на шарпе нет адекватных парсеров луа таблиц подходящих под методы конвертации рекомендуемые в интернете то за неимением альтернатив - json остаётся основным способом передачи данных с машины на сервер...чутка енкодер на клиенте покромсал(теперь он по кол-ву строк даже меньше основного кода клиента), использовал более правильные техники работы с таблицами и конкатенации строк и по идее он стал побыстрее чем до этого...
Но если есть предложения как всё-таки избавить клиент от необходимости как-то обрабатывать таблицы лишний раз перед отправкой то буду рад выслушать :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 часа назад, Darkar25 сказал:

@num_pi, порылся в инете и выяснил что луа из коробки не умеет конвертировать таблицы в строки (ну разве что table.concat или string.pack, но они подходят только для очень простых случаев, а для передачи например информации о результате сканирования геоанализатором нужно передавать таблицу полностью, вместе с подтаблицами)...и учитывая что на шарпе нет адекватных парсеров луа таблиц подходящих под методы конвертации рекомендуемые в интернете то за неимением альтернатив - json остаётся основным способом передачи данных с машины на сервер...чутка енкодер на клиенте покромсал(теперь он по кол-ву строк даже меньше основного кода клиента), использовал более правильные техники работы с таблицами и конкатенации строк и по идее он стал побыстрее чем до этого...
Но если есть предложения как всё-таки избавить клиент от необходимости как-то обрабатывать таблицы лишний раз перед отправкой то буду рад выслушать :)

Ну лично я использую костыль, но всё же рабочий. 

function convertArraytoLuaTable(array $array)
{
    $tmpHandle = tmpfile();
    fwrite($tmpHandle, json_encode($array, JSON_NUMERIC_CHECK));
    $data = shell_exec('/usr/bin/lua ' . realpath("decodeJsonToLuaFormat.lua") . ' ' . "'" . stream_get_meta_data($tmpHandle)['uri'] . "'");
    fclose($tmpHandle);
    return $data;
}

Здесь конвертация идёт из json в lua table, посредством вызова lua скрипта с диска, готовые данные можно считывать из temp файла создаваемого тобой заранее и передавать lua скрипту в качестве аргумента. Это что касается парсера lua table в json на стороне сервера. Ты имеешь ввиду, что, что бы отправить данные формат которых это таблица, её надо конвертировать в строку? И спрашиваешь как это сделать, лучшим образом, я правильно понимаю? 

Изменено пользователем num_pi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, num_pi сказал:

Ты имеешь ввиду, что, что бы отправить данные формат которых это таблица, её надо конвертировать в строку? И спрашиваешь как это сделать, лучшим образом, я правильно понимаю?

Верно. есть в луа таблица (table) и её надо в какой-нибудь формат перевести чтобы можно было перегнать с машины(компьютер/робот в майнкрафте) по сокету на сервер и там прочитать данные...на данный момент я эту проблему решил выдернув json енкодер с гитхаба и переделав его под свои нужды...если есть решение получше то хотелось бы его зачитать и возможно применить в этом проекте...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Пофиксил геоанализатор, Добавил недостающие проверки в классе агента, Добавил метод для получения направления взгляда робота без улучшения "Навигация"...

UPD спустя 4 часа:

Нашел на форуме парочку очень интересных тем: фильтрация шума геоанализатора и вычисление константы шума геоанализатора...добавил соответствующие методы в код сервера :)

Тема с фильтрацией шума

Тема с получением шумовой константы

UPD спустя 2 часа:

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

Изменено пользователем Darkar25

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

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

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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


×
×
  • Создать...