Just Another Sysadmin's blog (просто еще один блог сисадмина)

System log

И снова немного о планетах из кубиков
stasikos

Как же все-таки из шарика сделать кубик?

Конечно, когда я говорил, что надо пробовать делать "Майнкрафт со сферическим миром", я несколько размыто описал, как же все-таки в итоге можно сделать так, чтобы на поверхности все выглядело как плоскость из кубиков, а высоко вверху - как сфера. Хотя, признаюсь, сначала я отнесся к этому как-то по-наивному просто, решив, что можно и тупо перепрыгивать с левой стороны плоскости в правую и обратно, а на сферу просто такую "текстурку" натянуть, сделанную из плоскости.
Конечно, еще на этапе, когда я попытался сгенерировать такой мир, я понял, что генератор должен тоже понимать, что у него должен быть повторяющийся плавный узор из того, что он сделал, а не просто обрывать его в том месте, где нам больше не нужно ничего. Поэтому, да, есть такая вещь как Sphere в flow-noice, которая позволяет получать значения по координатам вроде долготы и широты в градусах.
И шо, вы таки думаете, что можно вот так вот взять и перенести полученные значения на плоскость? Вообще-то нет.
В общем, главным критерием "правильности" была возможность, в итоге, ползая по полученной плоскости обойти вокруг света за 8 шагов, если ты находишься прямо рядом с полюсом планеты. То есть никакой "растянутости" возле полюса быть не должно, а ведь она обычно есть, и эту проблему долго пытались решать картографы. Причем, если так подойти, то у вас на сферической проекции к полюсам такой широкий на плоскости мир сожмется до невероятно малых размеров.
Раздумия на эту тему, конечно, прошли не без гугла, ведь странно было бы, если бы этим никто еще не занимался. Да, я нашел кучу разных вариантов разной степени паршивости. Например, такой: https://en.wikipedia.org/wiki/Peirce_quincuncial_projection.
Но это не совсем хорошо для нашего случая. Самый крутой для меня вариант, который равномерно размазывает искажения, это проекция поверхности сферы на вписанный в нее куб, но не так, а немного иначе. По крайней мере, мне сейчас так кажется.
Ну и, конечно, нашлось, что это уже не новая идея: https://acko.net/blog/making-worlds-1-of-spheres-and-cubes/
И, получается, единственное, что здесь нужно, это преобразование координат из lat/long в x/y и конкретную поверхность "куба". Что, конечно, чревато некоторыми погрешностями на уровне плавающей точки, но я пока работаю над этим вариантом.
У этого последнего блога есть еще немного просто вдохновляющих и открывающих глаза идей вроде правильного использования SVO, которые выглядят красиво, но я еще не совсем понял, как потом этим пользоваться. И это тоже стоит попробовать.

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


Снова про эти воксельные движки
stasikos
Все-таки, в заду жжет и хочется изобретать велосипед. Однако, вместо очередной попытки сделать что-то в лоб я принялся за изучение имеющихся API, протоколов и внутренних структур Minecraft как одного из наиболее успешных (хотя, все уверены, что он "неоптимизирован", "криво написан", "тормозит потому что жава"). Узнал много интересного, развеял многие свои заблуждения насчет "да блин, это ж так просто". Смотришь так формат хранения/пересылки чего-то и видишь там много интересных особенностей. И начинаешь думать, можно ли сделать как-то иначе, и как-то в голову сразу ничего не приходит (особенно после опыта собственной "жырноты").

Например, о чем я сразу подумал плохо - это об объемах данных, которые нужно перегнать с сервера на клиент, например, чтобы показать мир в радиусе 80 блоков (то есть 10 чанков - по 5 в каждую сторону).
Примем ради простоты, что у нас каждый чанк состоит из 4096 блоков (16х16х16), и каждый блок у нас ничего кроме статичного ID не описывает. И пусть наш ID будет 32-битным (4 байта), потому что мы щедрые и хотим много блоков (или хранить какие-то дополнительные данные о них).
Если загрузить все полностью (и с этим, в принципе, я справился даже с жирнотой, в которой было больше 4-х байт на блок, просто все не так быстро было), то это 10*10*10 чанков, то есть тыща чанков... и если использовать даже по 4 байта на блок, у вас получается 16 мегабайт данных (4096*4*1000). Вроде-бы не космос какой-то для современных сетей. Но так и 10 чанков это не так много - это средние настройки для Майнкрафта. Максимум там 16 чанков (правда, это не радиус, а диаметр). Примерно 64 мегабайта (4096*4096*4), что чуть больше. 100-мегабитная сеть будет грузить это до 10 секунд. Конечо же, в идеале, нужно догнать и перегнать MC, отрисовывая не 8 чанков перед игроком, что всего-то составляет 128 блоков (128 метров). Размер блоков без снижения детализации позволяет рисовать гораздо дальше, создавая офигительный ландшафт, и надо увеличить это хотя-бы раза в два, но это будет не в 2 раза больше по объему, а в 8 (это ведь 3Д, Карл!), то есть, офигенная половина гигабайта (если быть точным, то 32*32*32*4*4096 байт).

Конечно, вы не хотите передавать от сервера клиенту полгигабайта данных (ну может меньше, за счет сжатия), поэтому нужно делать что-то еще, изобретая невероятные способы уменьшить эти объемы. Например, Minecraft целиком "пустые" куски чанков не передает вообще, совершает ряд манипуляций с blockID, чтобы вместо 2-х байт использовать иногда и один. Нам же придется кроме этого добавить и еще что-то вроде уменьшения числа данных о далеких чанках (такой себе LOD) и умные алгоритмы определения, надо ли их вообще загружать, что я уже делал, хоть и криво). И даже если не хочется очень далеко видеть, это очень нужно чтобы уметь быстро двигаться в мире.

Поэтому, кстати, Minecraft начинает как-то медленнее работать, если в него впихивают моды и ставят кучу блоков из них (хотя есть и другая причина, но о ней в следующий раз). Ну и еще стоит помнить, что кроме передачи этих данных по сети, их нужно на сервере хранить на диске и в памяти, и в памяти клиента тоже.

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

Очередной пост ни о чем
stasikos

В общем, помучался я еще со всякой оптимизацией этого офигительно амбициозного движка и понял, что все это слишком "толстая" затея не в том смысле, что она трудоемка, а в том смысле, что безнадежна. Хранить огромное количество данных о каждом блоке, помимо его типа - все-же слишком дорогая затея, передавать их по сети - слишком медленная. В общем-то, если и продолжать ковыряться в теме своего воксельного движка, то нужно вернуться к истокам - простым BlockID, которые просто хранят тип блока и так далее. То есть. по сути, просто написать еще один клон Майнкрафта. Чего делать не хотелось бы без благих целей.
Что касается геймплейных вопросов, связанных с реализмом и хардкорным выживанием, то тут товарищ тру_позер оказался прав. Я таки не думаю, шо кто-нибудь в здравом уме будет так мучиться и страдать и при этом еще и получать удовольствие. Скажем так, все это можно получить и с Майнкрафтом, только немного медленно и с лагами. Ставите себе какой-нить TerraFirmaCraft, или даже без этого - набор ReasonableRealism, GregTech, HungerOverhaul + EnviroMine. Во-первых, персонаж будет хотеть пить, во-вторых, быстро дохнуть с голоду, несмотря на поедаемые тонны стейков. Если добавить еще SpiceOfLife, он умрет еще быстрее из-за недостаточно разнообразной диеты. А потом его хватит тепловой удар. При наличии BetterSleeping он даже будет падать посреди дороги от усталости и дрыхнуть. Жаль только, что его бессознательную тушу не сожрут ночью без Somnia. Ну и если ему повезет выжить, то его сначала пару раз засыпет в шахте, а потом он задохнется от недостатка кислорода. А быть может, случайно подожжет метан факелом во время поиска первых залежей олова или меди и стремительно скончается, закрыв игру навсегда.
Короче, в топку. Я это все попробовал и мне уже не кажется моя старая идея такой хорошей. Хотя некоторые механики, возможные при грамотном подходе, все-таки могут быть интересными. Так что я таки не совсем забиваю на идею, а просто откладываю ее долгий ящик. На дозревание.


Всё не тлен
stasikos

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

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


Всё тлен
stasikos

Вот интересное состояние поймал в последний месяц. Оно нарастало плавно и вот теперь настало окончательно. Сегодня мне стало казаться, что вся деятельность лишена смысла. Сел делать очередную серию летс-плея, понял, что ее запорол с самого начала и нужно начинать заново (а это неделя возни). Есть не хочется, пить что-то тоже. Попробовал чай вместо кофе - полный шлак. Думать, писать код, всё что угодно - не вижу смысла. Залез в душ - не помогло совсем. Что бы ни начал делать, ощущение "получается говно и бессмысленно продолжать" не оставляет меня. С трудом заставляю себя писать этот пост, чтобы хоть какой-то анализ ситуации провести. Принял бы витаминку, но кончились. Сменил жижу на более веселую лимонную. Вылез на балкон, там солнце. Поразмышлял... вроде-бы стало немного легче, но не сильно

И как люди с этим обычно борются?


Размышления на тему генератора мира
stasikos

Пока я ковырялся с определением видимости чанков, передо мной встала проблема, как сделать что-то похожее на то, как это будет выглядеть в будущем. Конечно, тупо сделать один шум Перлина на весь мир - совсем не то, что должно получаться, с учетом всяких особенностей разных по климату и возрасту областей, но я уже имел честь повстречаться с некоторыми неприятностями.
Первая состоит в том, что шум, на самом деле, не самая быстрая вещь, которую можно придумать. А если еще и использовать много разного шума для разных особенностей ландшафта (например, пещер, как это делается в других играх), это может оказаться чрезвычайно медленно. Но, возможно, это не самая большая проблема - никто не будет генерировать огромное количество чанков с максимальным уровнем деталей, я полагаю. Однако, об этом еще придется подумать.
Вторая же проблема несколько более забавна - обычный шум хорошо работает на плоскости. И на первый взгляд тут есть серьезная проблема с тем, чтобы потом обернуть эту плоскость вокруг шара или чего-то еще, то есть, замкнуть в выбранных границах. В итоге не получается никакого плавного перехода, и это очень плохо выглядит. Но, к счастью, есть несколько методов решения этой проблемы - во-первых это четырехмерный шум, во-вторых, библиотека, которую я использую, позволяет менять модель шума и одна из моделей как раз называется "Сфера".
Конечно, применение шума для создания интересного ландшафта дело увлекательное и я чуть было не ударился в эту тему, забросив все остальное. Сразу же в голове начали крутиться мысли о том, как можно было бы с помощью него создать континенты и острова, молодые поросли гор с крутыми обрывами, каньоны и овраги, и реки, и всё такое прочее. Но это тема еще на месяц работы, как мне кажется. И, конечно, кроме формы ландшафта, должно быть и его содержание, то есть, разные минералы и прочие породы тоже как-то должны соответствовать форме этого ландшафта. Правда, тут есть и еще одна будущая проблема - как можно увидеть, что получилось, в большом масштабе? Форму в целом, в теории, можно натянуть на сферу и так и рендерить, возможно, даже раскрасить текстуру в какие-то цвета, и, конечно, чтобы не генерировать овердофига блоков, нужно делать это в низком разрешении, но будет очень сложно узнать, что же получилось под поверхностью. Вообще, интересно, как это можно было бы сделать, не запуская после каждого мелкого изменения заново всю симуляцию и не пытаясь что-то копать.


Статус воксельного движка
stasikos

Похоже, пока я размечтался о крутых особенностях физически обоснованной игровой механики в воксельных мирах, я недооценивал проблемы производительности при отображении мира игроку. Начнем по-порядку.
Я уже говорил раньше, что для более быстрого рендера блоков на экране, их пришлось собрать в группы, которые обычно называют чанками и рисовать уже чанки. Дальнейшие опыты показали, что довольно тупым и неэффективным путем Майнкрафта у меня идти не получается. Дело в том, что конечность высоты мира в Майнкрафте позволяет там считать чанком целый столбец мира высотой в 256 блоков, что, конечно, позволяет рисовать намного меньше поверхностей этих самых блоков изначально. Поэтому, тупо загрузить N * N * N чанков вокруг игрока оказалось жутко неэффективной затеей. Еще более неэффективным ее делала большая разница в представлении блоков. В Майнкрафте у блока просто есть одно число, которое полностью описывает "материал" и "положение" блока, скажем, его ориентацию, если она важна. Или это же число используется для запаковки множества похожих типов блоков, например, разноцветных блоков шерсти или глины. Понятное дело, это изначально показалось мне слишком жестким и мне захотелось расширить число свойств блоков, сразу позволив хранить целые списки разных значений. Конечно, это сразу же значит, что, во-первых, блоки занимают больше памяти, во-вторых, передаются по сети дольше. Так что вместо каких-то двух байт на тип блока, у меня получается все довольно толстым. С учетом того, что Майнкрафт и дальше немного оптимизирует эту часть протокола в последних версиях, они, наверное. о чем-то догадываются. Я об этом догадался не сразу, так что время доставки чанка с сервера на клиент оказалось великоватым, и даже если рендеринг успевает хорошо рисовать кучу поверхностей, обеспечить приемлемый радиус отрисовки уже становится трудным, потому что, мать их, чанки с сервера приходят долго. А то что они занимают сокет передачей, лишает некоторой плавности синхронизацию движения игрока в клиенте и сервере. В общем, время передачи чанков на клиент оказывается очень критичным (или нужно изобретать протокол вроде FTP, который бы использовал отдельное соединение для данных чанков). Значит, сообщения должны быть короче, а чанк придется разбить на части при передаче.
Но это еще не вся проблема. В сервере придется понятие "чанк" реализовать тоже, чтобы оптимизировать поиск и отправку всех блоков из запрошенного чанка. Раньше, когда он не мог оперировать таким понятием, ему приходилось вычислять, какие блоки из каких мест нужно вычитывать и последовательно их выдергивать. Я подозреваю, что это слишком медленно.
Но наилучшее решение, которое я нашел для этой проблемы, это оптимизировать число чанков, которые нужно загружать с сервера. Правда, эта часть до сих пор работает очень нестабильно. Работает это так: сначала вокруг игрока загружается минимальная область, скажем, 4х4 чанка. Далее, в текущей реализации, вокруг этой области клиент проверяет, видно ли каждый соседний, еще не загруженный чанк, разыскивая пересечения лучей от углов чанка до игрока и проверяя, сталкивается ли он с непрозрачным блоком внутри такого чанка. Однако, это, видимо, недостаточно точная проверка, потому как игроку не обязательно видеть углы, чтобы видеть кусок какой-то поверхности. И здесь интересно подумать, как сделать это лучше. Но уже так можно не загружать большое количество лишних данных с сервера. Возможно, если эту методику скрестить с понижением уровня детализации для дальних чанков, может быть возможным значительно увеличить дистанцию, на которой можно что-то разглядеть.
Печально в этом всём то, что постоянно приходится переписывать большие куски кода повсюду, так что даже нормальное, приемлемое по производительности, рисование одного типа блоков, похоже, будет возможным еще не скоро. А хотелось бы все-таки заняться чем-то более веселым, например, тем же движением игрока и обнаружением его столкновений с блоками.


Про электронные сигареты
stasikos

Не хотел торопиться об этом говорить, но, похоже, после двух недель такого существования я набрал немного опыта. Не все знают, но я курю уже 11 лет и в последнее время меня это стало понемногу напрягать, потому что курить я стал по две, а иногда и больше, пачки в день, и с прошлой попытки бросить стало только хуже. Так что, совершенно случайно заметив, как выглядит и работает современная электронная сигарета, я приобрел себе одну неплохую из тех, что можно посоветовать начинающим - Kanger EVOD Mega. Также, по незнанию, я взял пару разных жидкостей для нее, обе с 6 миллиграммами никотина на 1 миллилитр. Этого, правда, оказывается мало для того, кто курил много, но уже в первые дни обычные сигареты стали интересовать меня намного меньше и я почти не возвращался к ним, выкуривая где-то десяток в день. Спустя несколько дней, в течение которых я немного погуглил, изучил тему и оказалось, что мне стоило выбрать что-то намного более крепкое, и после перехода на 18 мг курить мне не хочется совсем, а один запах дыма вызывает неприятную реакцию. Но о реакции позже. :)
Сразу я обратил внимание, что у вновь начинающих наблюдается какая-то болезнь ньюфага, когда они восторжено начинают рассказывать и пропихивать идею перехода на парилки с курилок. Оно и понятно, потому что впечатлений куча. Первое начинается тогда, когда небольшое количество угарного газа, образующегося при горении, уходит из крови и позволяет транспортировать больше кислорода. От этого, в первую очередь, начинает наблюдаться покалывание конечностей, как бывает, если на них долго лежали и вдруг встали и дали крови нормально циркулировать. Это вызывает необычайное желание бегать, прыгать и рассказывать, как же это круто, парить эти новые штуки. Кроме того, попытки курить вызывают недоумение, потому что вкус и запах дыма уже не так интересны. Но все еще может оставаться тяга к сигарете, потому что в дыме не только никотин вызывает привыкание (гугление позволило узнать, что там еще с десяток веществ, которые имеют тот же эффект). Кроме того, никотин всасывается медленнее и не сразу попадает туда, куда нужно, чтобы тяга пропала моментально, как это бывает при курении.
Потом, правда, эйфория проходит. Где-то через неделю у меня полностью пропал вкус жидкости при парении и это вызвало новый позыв гугла об этой проблеме. Оказалось, это обычное дело и оно проходит само собой. На мое счастье, вкус пропал не полностью, так что еду и напитки я мог нормально воспринимать. Бывает хуже. Прошло это дня через три.
В остальном, тело испытывает симптомы обычного отказа от курения, включая бессонницу и сонливость одновременно, проблемы с пищеварением и все то прочее, что обычно бывает, включая обострение хронического бронхита на пару дней, повышенное выделение мокроты и насморк. Последнее у меня к настоящему моменту прошло. Теперь все кажется вполне обычным делом, однако напрягает возможная реакция окружающих на такую штуковину и связанная с этим проблема парить на ходу.
Однако, особо хочется отметить то, какую реакцию теперь вызывает запах дыма обычных сигарет. Причем, эта реакция намного слабее, если это дым сигары или трубки, например. Этот запах стал жутко раздражать. Я стал замечать этот запах повсюду и даже просто идти по улице стало неприятно, так как число курящих, оказывается, очень велико и они повсюду, они разного пола и возраста. И их запах распространяется на десятки метров вокруг. Так я осознал, насколько антисоциальным было мое прошлое поведение. По сравнению с этим парение, конечно, куда менее раздражает окружающих, так как запаха почти нет и он не такой противный, а иногда даже приятный.
В общем, если кто-то не может бросить курить обычными способами, рекомендую попробовать вот так. Во-первых, даже если после этого не удастся бросить и парить, это, вроде-бы, не так вредно, во-вторых, вполне вероятно, что путем понижения содержания никотина, можно будет и плавно от него отказаться, чтобы бросить совсем. Ну и для меня, в моей стране, это относительно более дешевый способ получения дозы никотина (правда это зависит от марки используемых расходников и частоты прошлого курения).


Внезапный ступор от ssh, su, nohup и &
stasikos
Сегодня одна вещь заставила поломать голову.

Допустим, у нас есть сервер, на котором есть какой-то шелл-скрипт, который хотят выполнять вот так:
$ ssh user@host sudo ./test.sh

Скрипт, например, содержит строку вида
su -c 'nohup daemon &'

Для проверки концепции я применяю sleep 100, но это не имеет значения:
#!/bin/bash
set -x
su -c 'nohup sleep 100 2>&1 > /dev/null &' root

exit 0

Логично для обычного обывателя предположить, что при выполнении скрипта он запустит некоторую команду, отвяжет ее от терминала и выйдет. Если запустить его из обычного терминала. так и произойдет:
Read more...Collapse )

Про Unit-тестирование
stasikos

Так уж сложилось, что я до этого времени писал довольно-таки много кода в разных мелких и не очень проектах, кусках проектов и прочего и нигде по-настоящему не применял такую штуку как юнит-тестирование. А уж тем более Test-Driven Development. Но для своего воксельного движка я решил попробовать хоть и не TDD, но хотя-бы тестирование разных методов классов. И даже некоторых классов целиком.
Сказать, что это не понравилось, я не могу. По-своему, это, конечно, требует иногда и дополнительных абстракций, которые кажутся совсем ненужными для нормалного, работающего кода, но зато это экономит время. Не так, чтобы прямо экономит время вообще, потому что оно также тратится и на написание и отладку тестов, но зато это позволяет потом в достаточной мере быть уверенным, что "баг где-то в другом месте". Сейчас я применяю тесты, в основном, для того, чтобы убедиться, что у меня правильно посылаются и парсятся отдельные сообщения между клиентом и сервером, или, например, что основные классы с объектами игрового мира правильно определяют координаты и не вылазят за пределы массивов при этом. Удобно то, что это можно сделать без компиляции и запуска всего проекта, включая отдельно сервер и клиент, что занимает, конечно, намного больше времени, чем нажатие Ctrl-F6 в IDE. Также это позволяет убедиться, что ничего не сломалось, после рефакторинга кода.
Конечно, мне даже хотелось сделать какое-то более тщательное покрытие тестами, хотя-бы половины кода, но я пока остановился на наиболее сложных частях кода и тех частях, где уже находились баги (или были сомнения. что они работают правильно). Но пока я пытался прикрутить анализ покрытия тестами, я узнал, что нормально работающий плагин для Maven, который работает с Java7/Java8 сейчас трудно. Emma не умеет 7-ю версию и выше, JaCoCo глючит и не работает, как мне показалось из списка рассылки, с проектами из множества модулей (а мой именно такой). Однако, я все-таки нашел, что Cobertura, во-первых, работает, во-вторых, все-таки встраивается в Netbeans, хотя добиться общего отчета по всем модулям я пока не смог. А еще оно иногда глючит и не работает.
В общем, штука полезная, хотя я к модным мейнстримным вещам всегда отношусь как-то с прохладой. Хотя автоматизация процесса тестирования вещь очевидная :).


?

Log in