Перейти к публикации

В ближайшее время постараюсь разобраться с картой сервера/ЛК/бб кодами

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

BarBoss

Робот пропускает движения.

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

Итак пишем прогу, которая бесконечно гоняет робота взад-вперёд :

 

local r = require("robot")
local component = require("component")
local long = 10 -- длинна участка.
local pause = 5

-- гоняем робота взад - вперёд

repeat

 for bb=1 , long do
 r.forward()
 end
 r.turnAround()

 os.sleep(pause)

 

 for bb=1 , long do
 r.forward()
 end
 r.turnAround()

 

 os.sleep(pause)

until false

 

И убеждаемся, что робот рандомно пропускает движения.

И не только движения. use() - тоже иногда пропускает.

Что делать, как быть?

 

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


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

Используй gcc для отладки.

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


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

Используй gcc для отладки.

 

Тут не в отладке дело. Что тут отлаживать? Три строки?

 

 

Итак пишем прогу, которая бесконечно гоняет робота взад-вперёд :

 

local r = require("robot")

local component = require("component")

local long = 10 -- длинна участка.

local pause = 5

-- гоняем робота взад - вперёд

repeat

for bb=1 , long do

r.forward()

end

r.turnAround()

os.sleep(pause)

 

for bb=1 , long do

r.forward()

end

r.turnAround()

 

os.sleep(pause)

until false

 

И убеждаемся, что робот рандомно пропускает движения.

И не только движения. use() - тоже иногда пропускает.

Что делать, как быть?

 

Да, действительно!

 

Просто цикл

for i=1 , 10 do 
   robot.forward()
end 

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

 

Во первых: No yield / sleep in the loop => нет гарантии правильной работы GC.

 

Во вторых:  сам метод robot.forward() то вызывается 10 раз, но так как он никак не проверяется и пытается выполнятся на огромной скорости, нет никакой гарантии, что он выполнился с TRUE. Проще говоря, может еще не наступить физическое перемещение робота, и следующий вызов метода выполняется с FALSE и перемещение пропускается. Так писать движение робота, видимо, нельзя!

 

Вот маленькая корректировка программы: 

local r = require("robot")
local component = require("component")

local long = 10 -- длинна участка.
local pause = 5

local function forward()
	while not r.forward() do
		os.sleep(1)
	end
        os.sleep(0)
end

-- гоняем робота взад - вперёд
while true do
	 for i=1 , long do 
	 	forward()
	 end 
	 	r.turnAround()
	 os.sleep(pause)
	 for i=1 , long do 
	 	forward()
	 end 
	 r.turnAround()
	 os.sleep(pause)
end

Здесь функция 

local function forward()
	while not r.forward() do
                --я написал паузу, но можете атаковать, разрушить блок и прочее, поставить любую задачу роботу
		os.sleep(1) 
	end
        os.sleep(0)
        --здесь можно увеличить координату и вернуть TRUE	
end

дождется выполнения перемещения, пока метод r.forward() не вернет TRUE. Робот переместится и цикл for пойдет дальше. Это гарантировано убережет нас от затыков сервера, маленьких подлагиваний и прочего. Иначе, вы не выполните четко 10 перемещений!

 

Вот робот стал кататься четко по меточкам, даже если вы встанете на пути или положите камешек, а потом уберете:

 

zRatW5u.png

 

До корректировки, да, он катался на случайное количество блоков, когда на 10, а иногда и на 3 или 4, потом разворачивался.

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


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

<p>Farlang - человек, который написал ферму с проверкой передвижений по координатам, лежит в готовых прогах</p>

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


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

<p>Farlang - человек, который написал ферму с проверкой передвижений по координатам, лежит в готовых прогах</p>

Там проверка движений очень тупая на самом деле, просто рекурсивным вызовом.

Этот способ:

local function forward()
	while not r.forward() do
		os.sleep(1)
	end
        os.sleep(0)
end

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

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

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


Ссылка на сообщение
Поделиться на других сайтах
Farlang сказал(а) 23 Апр 2015 - 07:54:

 

Там проверка движений очень тупая на самом деле, просто рекурсивным вызовом

Будь добр, кинь ссылку на код с умной проверкой)

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


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

Решение проблемы методом контроля исполнения команды передвижения, безусловно, рабочее. Но ведь робот не только движется. use() он тоже пропускает (хотя и много реже). Как её контролировать? А другие функции?  Эдак мы придём к тому, что нужно весь API робота переписать. Что-то тут не то. Разработчик мода просто не мог такой проблемы не предусмотреть.

Я играл на разных серверах с OC и на всех были лаги и фризы. Куда ж без них. Визуально робот застывал, а потом мгновенно перемещался на несколько позиций выполнив работу. Здесь же он застывает на месте, команды не исполняются. Такое впечатление, что сервер не успевает всё обработать, но вместо снижения TPS просто сбрасывает часть очереди, не обработав её. В их числе оказываются и "заявки" на действия роботов от виртуальных машин Lua. Для роботов такая рассинхронизация фатальна. Перемещение - это лишь часть проблем, то,  что явно видно.  :(

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


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

Решение проблемы методом контроля исполнения команды передвижения, безусловно, рабочее. Но ведь робот не только движется. use() он тоже пропускает (хотя и много реже). Как её контролировать? А другие функции?  Эдак мы придём к тому, что нужно весь API робота переписать. Что-то тут не то. Разработчик мода просто не мог такой проблемы не предусмотреть.

Я играл на разных серверах с OC и на всех были лаги и фризы. Куда ж без них. Визуально робот застывал, а потом мгновенно перемещался на несколько позиций выполнив работу. Здесь же он застывает на месте, команды не исполняются. Такое впечатление, что сервер не успевает всё обработать, но вместо снижения TPS просто сбрасывает часть очереди, не обработав её. В их числе оказываются и "заявки" на действия роботов от виртуальных машин Lua. Для роботов такая рассинхронизация фатальна. Перемещение - это лишь часть проблем, то,  что явно видно.  :(

 

Но факт. Я вчера был сам удивлен немного, что робот не выполняет, как положено 10 перемещений=)

for i=1 , 10 do 
   robot.forward()
end 

Сам в шоке. Хоть и такими циклами редко пользовался. Проверь в сингле. Раньше, кстати никто не жаловался. Сервак уже 4 месяца маслает. Первый раз от тебя услышал, что у вас там на МТ такое, а теперь и на ИТ. По идее он дожен выполнить их!!! Но нет. Может как-то это связано с обновлением мода и прочее.

 

Но раньше я не слухом не духом не слыхивал, что робот может проехать пять блоков вперед, копая под собой блоки и какой-то блок пропустить! Это нонсенс!!!!!!!

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


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

Практически все команды робота возвращают true/false как индикатор успеха выполнения.

Если вы вызываете еще один forward в то время, как робот еще предыдущий не завершил - не ждите, что он "включит нитро" и понесется быстрее.

Проверяйте, и будет все хорошо. И организуйте ему слипы в цикле. Во время слипов обрабатываются эвенты и фоновые задачи.

  • Like 1

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


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

Практически все команды робота возвращают true/false как индикатор успеха выполнения.

Если вы вызываете еще один forward в то время, как робот еще предыдущий не завершил - не ждите, что он "включит нитро" и понесется быстрее.

Проверяйте, и будет все хорошо. И организуйте ему слипы в цикле. Во время слипов обрабатываются эвенты и фоновые задачи.

Во-во, про нитро-ускорители тоже была мысль  :D

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


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

Черепашки рулят.

  • Like 1

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


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

Черепашки рулят.

Черепашки курят)

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


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

 

> Практически все команды робота возвращают true/false как индикатор успеха выполнения.

 

Не всё так просто. Попытайтесь применить true/false для функции use() выполняемой над кропсом, растущим на жердочке, а я посмеюсь. Даже объехать на кривом козле с геолизером это нельзя - нет способа получить состояние кропса.  Перемещение - это лишь самые примитивные и очевидные команды.

 

 

 

Если вы вызываете еще один forward в то время, как робот еще предыдущий не завершил - не ждите, что он "включит нитро" и понесется быстрее.

Проверяйте, и будет все хорошо. И организуйте ему слипы в цикле. Во время слипов обрабатываются эвенты и фоновые задачи.

 

Этокакэто? У нас сервер в несколько потоков работает? И один поток пихает в очередь другого задачи асинхронно,  не интересуясь выполнением предыдущей команды? Иначе описанное Вами "нитро" нереализуемо.

А вот то, что я вполне допускаю - сервер при перегрузке сбрасывает с очереди обработки низкоприоритетные задачи - падение гравия, распространение воды, мобов и т.д. в это я готов поверить. И движение роботов попало туда-же. При том, что виртуальная машина lua осталась высокоприоритетной и добросовестно исполняется. Результат на лице.

P.S. Это лишь мои домыслы. То, как я реализовал бы обработку будучи разработчиком серва. Реально работы сервера я не знаю.

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


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

Может есть смысл взять ванильный майн, дефолтный мод ОС и в одиночке потестить работу программы, которая в шапке темы?

Тогда мы отметаем все серверные заморочки, рассинхроны, приоритеты, лаги, шмаги и прочее. Это многое должно прояснить. Возврат функции сразу на экран принтить.

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


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

В одиночке нормально всё. Пробовал я.

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


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

Не всё так просто. Попытайтесь применить true/false для функции use() выполняемой над кропсом, растущим на жердочке, а я посмеюсь. Даже объехать на кривом козле с геолизером это нельзя - нет способа получить состояние кропса.  Перемещение - это лишь самые примитивные и очевидные команды.

 

Этокакэто? У нас сервер в несколько потоков работает? И один поток пихает в очередь другого задачи асинхронно,  не интересуясь выполнением предыдущей команды? Иначе описанное Вами "нитро" нереализуемо.

А вот то, что я вполне допускаю - сервер при перегрузке сбрасывает с очереди обработки низкоприоритетные задачи - падение гравия, распространение воды, мобов и т.д. в это я готов поверить. И движение роботов попало туда-же. При том, что виртуальная машина lua осталась высокоприоритетной и добросовестно исполняется. Результат на лице.

P.S. Это лишь мои домыслы. То, как я реализовал бы обработку будучи разработчиком серва. Реально работы сервера я не знаю.

 

Функция use() возвращает true/false так же, как и остальные функции. В случае true добавляет описание произведенного действия.

Под "робот пропускает действия" имеется ввиду, что робот возвращает "успех операции" не выполняя ее физически?

 

По поводу мультипоточности я погорячился, да. Мне уже указали тут. Что, однако, не отменяет необходимости ставить слипы и делать проверки.

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


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

Функция use() возвращает true/false так же, как и остальные функции. В случае true добавляет описание произведенного действия.

Под "робот пропускает действия" имеется ввиду, что робот возвращает "успех операции" не выполняя ее физически?

 

По поводу мультипоточности я погорячился, да. Мне уже указали тут. Что, однако, не отменяет необходимости ставить слипы и делать проверки.

Поэкспериментирую с кропсами завтра. Засада в том, что понятие "успех операции" весьма неоднозначно. false будет в двух случаях - если кропс не вырос и если действие пропущено. Как реагировать? Повторить? Игнорировать? Вангую такую ситуацию во многих случаях. Проверить состояние кропса нечем.

 

Слипы в этой ситуации ничего принципиально не меняют. Я добавлял слипы в несколько секунд - эффекта вообще никакого. Если сервер сбросил запрос на обработку действия - ждать можно до морковкиного заговения. Проверять исполнена ли каждая команда - это нонсенс. Это нужно практически API робота переписать - не пихать же это счастье в каждую программу сызнова. Ведь робот не только двигается. А всякие апргрейды? Работа с жидкостями, инвентарём и прочее?  Это же тихий ужас. И самое главное - раньше такой проблемы не было. ИМХО, тут в консерватории что-то не так.

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

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


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

Да, тоже раньше не слышал о такой проблеме.

Рекурсивный майнер пахал сутками без сбоев. А там алгоритмы достаточно высокой точности требуют.

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


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

Да, тоже раньше не слышал о такой проблеме.

Рекурсивный майнер пахал сутками без сбоев. А там алгоритмы достаточно высокой точности требуют.

 

Вот именно! Там все работало, как часы, и нет там проверок на TRUE.  Нужно безотлагательно создать экспертную комиссию и прозондировать этот вопрос более  тщательно. Вплоть до петиции Сангару. Проверки раньше были в  основном необходимы именно для убеждения, что робот дейсвительно продвинулся, и там нет преграды, блока.

 

Но цикл

for i=1 , 10 do 
   robot.forward()
end 

работал, если у робота нет ничего на пути, он 10 перемещений совершал, это к бабке не ходи :D

 

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

 

А может это фича, связанная с оптимизацией? Может так и должно быть, а мы ламеры и не знаем всей глубины глубин задумки Сангара?=)

  • Like 1

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


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

я тоже столкнулся с этой проблемой, но после долгих экспериментов и испытаний я отладил программу, теперь никаких пропусканий нет вообще. Как оказалось, метод robot.forward() никогда не возвращает false, если пройти не удалось он возвращает строку с причиной, и (как я думаю) она преобразуется в true. Вот фрагмент кода, который работает безотказно:

  function move(m)

    i = 1

    while i <= m do

      dig()

      if  robot.forward() == true then -- тут ==true ключевой момент, без него не работает корректно

        i = i + 1

      end

    end

  end

 

З.Ы. Я новичёк в LUA и в OC, да и в программировании тоже, если ошибаюсь, скажите где. Но программа работает, проверено много раз, если надо скину исходники.

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


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

Проверил в простом варианте сегодня движения. Циклов 100 наверно сделал туда сюда на 10 блоков. Ничего робот уже не пропускает (я по крайней мере не выявил косяков), катаясь в воздухе. Видимо была проблема в версии (обновил с тех пор, с 23 апреля) и OS новая.  Скорее всего там был косяк.

 

При посте первом, 23 апреля, когда  BarBoss написал, да, уже на втором или третьем развороте робот начал стопориться и не выполнял 10 движений в форе.

 

Но реально, если перед роботом ничего нет, он должен треснуть, но выполнить 10 перемещений в цикле

for i=1 , 10 do
   robot.forward()
end

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

 

По идее, метод robot.forward() должен начать и закончить перемещение (или вернуть nil и причину [string],  если не может робота переместить) и только тогда отдать управление дальше программе. Как бы там даже сервак не лагал и прочее, пропусков не должно быть.

 

И их сейчас по состоянию на 15.05.2015, 01:00 по МСК я не обнаружил.

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


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

Что довольно странно, но делал программки на MC 1.8 с последним OC и встретил этот баг, решил проверить на 1.7.10 - аналогично.
К примеру в этом коде:

robot.swingDown()
robot.down()
robot.swingDown()
robot.up()

стабильно игнорится вторая строчка, при чем другие движения/взаимодействия работают довольно четко, но в паре с функцией swing происходят ошибки (иногда даже путает слоты инвентаря). Слипы не помогают, что делать?  :smile14:  Переписать robot API?

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

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


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

Создаём файл /lib/robo.lua, например, и пишем что-то типа этого (не тестил, будет ли работать):

local robot = require("robot")
local attempts = 5 -- Указыавет, сколько следует сделать попыток выполнить данное действие


local function tryToDo(func)
  local success = false
  for i = 1, attempts, 1 do
    if not func() == true then
      os.sleep(0.5)
    else
      success = true
      break
    end
  end
  return success
end

local funcsToOverride = {"down", "up", "turnLeft", "turnRight", "forward", "swing"} -- просто заполняем список функциями для перезаписи на стабильные версии
for i = 1, #funcsToOverride, 1 do
  robot[funcsToOverride[i]] = function()
      local success = false
      for i = 1, attempts, 1 do
        if not robot[funcsToOverride[i]]() == true then
        os.sleep(0.5)
      else
        success = true
        break
      end
    end
  return success


    end
end
return robot
Изменено пользователем Fingercomp
  • Like 1

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


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

 

Создаём файл /lib/robo.lua, например, и пишем что-то типа этого (не тестил, будет ли работать):

local robot = require("robot")
local attempts = 5 -- Указыавет, сколько следует сделать попыток выполнить данное действие


local function tryToDo(func)
  local success = false
  for i = 1, attempts, 1 do
    if not func() == true then
      os.sleep(0.5)
    else
      success = true
      break
    end
  end
  return success
end

local funcsToOverride = {"down", "up", "turnLeft", "turnRight", "forward", "swing"} -- просто заполняем список функциями для перезаписи на стабильные версии
for i = 1, #funcsToOverride, 1 do
  robot[funcsToOverride[i]] = function()
      local success = false
      for i = 1, attempts, 1 do
        if not robot[funcsToOverride[i]]() == true then
        os.sleep(0.5)
      else
        success = true
        break
      end
    end
  return success


    end
end
return robot

То, что надо! Ща затестим...

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

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


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

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

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


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

надо ОЗУ больше (помню эту проблему, и как над ней с тоторо мучались)

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


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

Создайте аккаунт или войдите в него для комментирования

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

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×