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

RemoteOS - C# мост

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

Что такое 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 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. Дата-карты 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

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

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

 

Веб сервер:

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

На данный момент веб сервер имеет довольно скудный функционал - только бегать роботами по карте и сканировать всё вокруг.
На сайте имеется Waila, дебаг информация (F4), полноценный рендер блоков.

Для начала работы с сайтом нужно запустить веб сервер и подключить к нему одного или более роботов/компьютеров/дронов(тестировалось только на роботах, но в теории должно работать исправно и с остальными типами машин).
После того как робот подключился к серверу он появится в списке машин слева сверху и будет иметь один из нескольких статусов:
OFFLINE - машина оффлайн, управлять ей сейчас нельзя. в этом статусе можно только изменять координаты машины.
AWAITING POSITION - эта машина впервые подключилась к серверу и необходимо установить координаты нажав на эту кнопку
READY - машина онлайн и готова к управлению. при нажатии на эту кнопку машина перейдёт в статус SELECTED
SELECTED - текущая выделенная машина которой вы сейчас управляете
После того как вы выбрали робота вы можете управлять им используя кнопки WASD, Shift(опуститься вниз), Space(подняться наверх).

Управление камерой:
ЛКМ - Вращать камеру
ПКМ - Перемещать камеру
СКМ - Приблизить/Отдалить

На сайте установлены такие "моды" как minecraft, opencomputers, wailaharvestability, remoteos(модельки для роботов и дронов). чтобы установить дополнительные моды необходимо закинуть в папку wwwroot/assets необходимые ассеты(текстуры, модели, файлы локализации). я постарался сделать так, чтобы сайт требовал минимального вмешательства в ассеты для установки, но к сожалению иногда приходится делать мапперы для файлов локализаций и менять модели чтобы они корректно загружались на сайте.

Скриншот сайта:
Screenshot-1636.png


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

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

Ссылки

Репозиторий проекта: Тык (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

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


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

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

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


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

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

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

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

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

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

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

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

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


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