суббота, 16 января 2016 г.

[SL] Популярные скрипты. TIP-JAR

TIP-JAR

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

Но на самом деле тип-джаром может стать совершенно любой объект (конечно же, с правом modify, чтобы его можно было редактировать), если в него положить нужный скрипт. Такой скрипт можно взять из какого-нибудь бесплатного тип-джара, а можно написать самостоятельно.

В этом есть свои плюсы - вы будете точно знать, как это работает, да и всегда можно покрасоваться перед своими друзьями - дескать, сам написал! Круто же, не? ;)

На самом деле любой тип-джар являет собой крайне простой скрипт, основанный на событии money(), которое возникает каждый раз, как кто-то заплатит вашему объекту денег. Сами же деньги при этом попадают прямиком владельцу предмета.

  • Здесь нужно быть внимательным, потому что если у вас владельцем тип-джара окажется группа, все деньги будут уходить в группу!
Но для того, чтобы это событие стало происходить и объект начал принимать деньги, а это свойство, повторюсь, объекту дает только специальная настройка и скрипт, всё это нужно правильно подготовить, то есть инициализировать.



 Создайте объект и назначьте действие по умолчанию при клике на объект - "Платить объекту". В этом случае пользователь будет получать стандартное окошко оплаты с установленными ценами.


Цена устанавливается при помощи функции llSetPayPrice() в самом начале. Синтаксис прост:

llSetPayPrice(цена в окошке, [цена на кнопке, цена на кнопке, PAY_HIDE, PAY_HIDE]);

Собственно всё, уже этого всего вполне достаточно, чтобы объект принимал деньги и передавал их своему владельцу! И весь основной скрипт, реально, несколько строк. Смотрите сами:


Осталось только сделать интерфейс - то есть чтобы люди понимали, что это тип-джар, выводить какую-то информацию и благодарить донатора. Это делается просто такими функциями, как llSay() (сказать в общий чат) и llSetText() (вывести текст над объектом).

Усложняем наш скрипт - здесь я не буду досконально рассматривать каждую команду, если что-то не понятно, спрашивайте. А скрипт будет таким:
Ради прикола я добавил в конце проигрывание двух стандартных звуков - звонка кассы и телепорта. Типа, тю-тю, улетели денежки ;)




 

пятница, 25 сентября 2015 г.

Говорящий бот с псевдоинтеллектом

Надо же, практически год назад я тут писал пост... Все ж в нашем мире любой процесс имеет циклическую природу... Ладно, не будем зацикливаться ;)

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


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


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

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

Я вот тут положу скан такой таблицы (да-да, они реально существовали!), попробуйте сами, это, по крайней мере, довольно весело ;)


Несколькими годами ранее на Плюке Менькой был сделан LSL-бот "Эд", который проигрывал аудиофразы в случайном порядке при возникновении события столкновения с кем-либо и нудел, я вас заверяю, на отлично; было очень похоже на реального Эда в тот период.

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

Вот что я еще хочу сказать, дорогие читатели - в инженерном искусстве важно найти кратчайший путь решения задачи для достижения технической цели. Это очень важно помнить при выборе инструмента, при помощи которого вы хотите ее достичь. В данном случае речь идет о том, какой язык при этом выбрать. Но на самом деле это совершенно не важно до тех пор, пока не конкретизирована цель. Предложенный сценарий несложно реализовать, используя лишь LSL и подход Меньки к вопросу. А можно все написать самому "с нуля" (привет, Вэб!) на C/C++, включая бота и войс для него. Этот путь интересен и познавателен и я, кстати, ходил по нему :D

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

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

В первую очередь необходимо сформировать базу фраз. Если вы делаете автодиджея или рекламного агента, то рекомендую сесть и написать не менее ста предложений примерно одинаковой длины. Затем разбить их на словосочетания и разместить из в таблице. Затем, пробуя таблицу, что-то подкорректировать.

А затем записать уже голосом, проходя таблицу подряд сверху до низу. Обязательно засеките среднее время звучания предложения, это будет важно! Далее вы разрезаете вашу запись на аудиофразы, при этом не обрезайте тишину - она необходима для правильного восприятия, просто постарайтесь резать посередине.

Получившиеся файлики разложите по количеству папок, равное кол-ву столбцов вашей таблицы. То есть каждая папка - это столбец таблицы.

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

Вот теперь можно перейти к коде этого марлезонского балета - вдохнуть разум и сознание в эту кучку цифрового песка. Ведь чем мы занимаемся? Големов строим! Пусть и виртуальных... ;)

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

Итак, сперва сделаем источники:

phrases1 = playlist(reload = 300, "/home/androbot/phrases1")
phrases2 = playlist(reload = 300, "/home/androbot/phrases2")
phrases3 = playlist(reload = 300, "/home/androbot/phrases3")
phrases4 = playlist(reload = 300, "/home/androbot/phrases4")
То есть мы сказали LiquidSoap'у, что нужно рассматривать папки, как плейлисты, а параметр "reload" говорит о том, что каждые 300 секунд нужно перечитывать список файлов. Это позволит вам добавлять новые фразы без перезапуска основной системы - частенько это бывает важно.

Перемешаем всё:

phrases1 = random([phrases1])
phrases2 = random([phrases2])
phrases3 = random([phrases3])
phrases4 = random([phrases4])

К слову сказать, по умолчанию плейлист и так рандомизирован, но и LiquidSoap штука сама по себе настолько магическая, что перемешать еще раз не помешает, простите за каламбур ;)

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

Создаем очередь:

proposal = rotate(track_sensitive = true, weights = [1,1,1,1], [phrase1, phrase2, phrase3, phrase4])

Вообще, конечно, этот оператор не для этого, но в данном случае он нам формирует последовательную очередь из четырех треков четырех источников с ожиданием концов треков. Кому интересно подробнее - в документации всё есть ;)

В принципе, всё, если сейчас отдать переменную proposal проигрываться, мы получим постоянный бубнеж.

Делаем некие магические пассы (документация!):

voice = mksafe(proposal)

И отдаем в звуковую карту напрямую (я это делаю при помощи pulseaudio, у вас может быть что-то другое, это при установке выясните):

output.pulseaudio(device = "Androbot", voice)

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

Помните, я говорил, что нужно запомнить среднее время звучания предложения? Основываясь на этих данных мы прикинем, когда нашему боту говорить и сколько, скажем... Скажем, в рамках часа - ведь база у нас невелика. Допустим, он должен говорить каждые двадцать минут, сначала две минуты, потом три минуты, потом одну с половиной минуты. Ну и допустим, что одно предложение у нас занимает 10 секунд.

voice = fallback(track_sensitive=false, [
        switch(track_sensitive=true, [
                ({(00m05s-02m05s) or (20m20s-22m20s) or (53m40s-54m40s)}, proposal)
        ]), blank()
])

Я также позволю себе не вдаваться в подробности работы этой конструкции - важно лишь понять, как работает синтаксис указания времени. В данном случае в потоке у нас будет либо тишина, либо, если время (глобальное) попадает в указанные интервалы, бот будет говорить. У нас он заговорит в 5 секунд после начала каждого часа, потом в 20 минут 20 секунд и в 53 минуты 40 секунд. Вы можете задавать свои интервалы, разделять предложения паузами, для этого вам и нужно знать, сколько длиться предложение - тут дело тонкой настройки бота, которое напрямую зависит от ваших требований и вашей базы.

Ну, а дальше, все просто, мы это уже делали раньше:

voice = mksafe(proposal)
output.pulseaudio(device = "Androbot", voice)

Всё! Когда наступит указанное время, бот заговорит человечьим голосом. Конечно, этого всего еще мало для полноценного автоматического диджея, но никто же не обещал, что я раскрою все секреты, верно? ;)

До новых встреч, девочки и мальчики.

пятница, 26 сентября 2014 г.

«AlphaSMS» - сервис доставки SMS-сообщений

UPD: В настоящее время сервис закрыт по юридическим причинам (невозможность удовлетворить все требования новых поправок к Закону о связи РФ) и выставлен на продажу в виде исходного кода. По вопросам приобретения кода и прав на него связываться с Manoul Carnell в SL.

Как видно из названия, «AlphaSMS»доставляет sms-сообщения, отправленные из Second Life на мобильные телефоны. Более того, сервис доставит вам ответное сообщение обратно, в уютненький Second Life. «Надо же, как просто! Но я могу и так отправить sms, с телефона, зачем оно мне нужно?» - спросит иной пользователь и я отвечу.

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

Думаете, это настолько банально? Вот уж, раз отвлеклись изначально от технической стороны, то давайте рассмотрим чисто житейскую ситуацию.

Мальчику нравится девочка, мальчик дарит девочке пейджер и сообщает свой номер телефона. Теперь девочка, заметьте, не оставляя своего номера мальчику (будем надеятся, до поры), может слать ему всякие романтические глупости. И мальчик может отвечать ей. Не это ли прекрасно?

Итак, теперь немного картинок, показывающих, как все просто на самом деле.

Рис.1

Итак, HUD очень прост и изящен - функционально мигающая лампочка, показывающая состояние сети и текстовое оповещение. Чтобы отправить сообщение, нужно по нему кликнуть. К слову сказать, пейджер активируется только будучи надетым как HUD. Выложенный на землю он отключается, будучи же приаттаченым к другим частям аватара, выдаст сообщение о правильном расположении, после чего отцепится и упадет обратно в инвентарь.

Рис.2

Все меню русифицированы изначально, поэтому сложностей ожидать не приходится - надписи на кнопках говорят сами за себя. "Баланс" показывает текущий баланс, "Обновить" вызывает принудительный сеанс передачи актуальных данных с сервера (в обычном режиме пейджер постоянно, через равные промежутки времени обменивается данными, но мы же понимаем, что SL тормозит там, где не глючит, и наоборот), "Пополнить" - понятно зачем, ну и самая главная кнопка - "Отправить"!

Рис.3

При нажатии на нее появляется окно отправки сообщения, где нужно указать телефон и сообщение. К сообщениям применяются все те правила, которые применяются к обыкновенным смс. На этом рисунке я не стал тянуть кота за хвост и сразу разместил скриншот с телефона. Сообщения доставляются относительно быстро, однако следует понимать, что операторов хватает и у каждого свои очереди доставки и другие странности, поэтому на разные операторы сообщения будут ходить каждое по-своему. Да и обычные смски ходят тоже точно таким же макаром.
Ну и хотелось бы коснуться вопроса пополнения баланса. Как все понимают, только коммерческая составляющая заставляет работать что-либо пресловутым "должным образом", поэтому в системе «AlphaSMS» все сообщения платные. Стоимость сообщения вычисляется в реальном режиме на основании запрошенных данных от оператора, сколько будет стоить вот такая длина текста на вот такой номер. Минимальная цена у нас получилась 8 за сообщение на телефон МТС. Однако, я бы все же отдал предпочтение минимальной стоимости в 10 при отправке на телефоны РФ и СНГ, за границу же стоимость может достигать и 40. В дальнейшем, с выпуском международной версии, возможно удастся цены как-то нивелировать.

Рис.3

Как же пополнить баланс? Для этого были разработаны специальные карты пополнения баланса на 100, 250, 500 и 1500. Несмотря на номинал, принцип использования карт един - ее просто нужно выложить на землю там, где работа скриптов не запрещена. В углу появится меню, предлагающее пополнить баланс. Если отвечаем положительно, карта превращается в тыкву, а на ваш счет в системе поступает указанная в номинале сумма. Если же вы откажетесь, тогда карта напомнит вам сохранить ее в инвентарь.
Карты можно передавать, поэтому их можно запросто дарить. Как в нашем примере - мальчик дарит карту девочке на 8 марта, а 9 марта она ему выносить мозг смсками ;) Жуть.

Что же касается технологии, будет некрасиво не сказать ни слова о ней... Казалось бы, простая задача за многие годы, которые прошли со времен первых симов, так никто и не представил подобного решения. Видел решения с бесплатными email-sms шлюзами, но это, как вы сами понимаете, совершенно не гарантирует доставку, не говоря уже о каком-то адекватном времени, которое она занимает.

На проверку оказалось, что анархия с кодировками текста до сих пор, в эпоху интернетов и юникодов, остается проблемой. Поэтому был написан довольно хитрый модуль определения кодировок и превращению зюк в буквы. Еще одна проблема подстерегала на этапе стабильного линка гаджета к серверам системы - все-таки СЛ есть СЛ, сами знаете. Ну и третья, серьезная проблема, с которой пришлось столкнуться, является культура пользователей. Так как законы РФ с некоторых пор ополчились на старый добрый мат, то операторы так и ждут, чтобы оштрафофать контрагента за шалости его клиентов. Так как люди из СЛ очень любят литературно шалить в стиле Луки Мудищева, пришлось поставить мат-фильтр и запретить мат, вкупе с рекламой, пунктом в Договоре-оферте.

Осталось самое-самое - сообщить, где же можно пробрести пейджер. Учитывая гон и фокусы с банами за трансферы с ворованными линден-долларами, продажи пейджера и карт пополнения происходят только через маркет; никаких вендоров in-world, во всяком случае, моих. Поэтому все желающие могут пройти по ссылке и приобрести безопасно и с гарантией через официальный сайт - https://marketplace.secondlife.com/stores/9085

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

Наслаждайтесь! ;)

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

понедельник, 29 апреля 2013 г.

Сервис групп (вариант для начинающих администраторов)

Кто желает, может подключить на своих симуляторах сервис групп, сейчас я объясню, как это сделать. Рецепт даю для крайней версии сервера, однако полагаю, что на старших версиях все точно так же. Берем файл OpenSim.ini и находим там секцию [Groups], после чего приводим ее вот к такому виду

[Groups]
;# {Enabled} {} {Enable groups?} {true false} false
;; Enables the groups module
Enabled = true

;# {Module} {Enabled:true} {Groups module to use? (Use GroupsModule to use Flotsam/Simian)} {} Default
;; This is the current groups stub in Region.CoreModules.Avatar.Groups.
;; All the other settings below only really apply to the Flotsam/SimianGrid
;; GroupsModule.
;; This module can use a PHP XmlRpc server from the Flotsam project at
;; http://code.google.com/p/flotsam/
;; or from the SimianGrid project at http://code.google.com/p/openmetaverse
Module = GroupsModule

;# {MessagingEnabled} {Module:GroupsModule} {Is groups messaging enabled?} {true false} true
MessagingEnabled = true

;# {MessagingModule} {MessagingEnabled:true} {Module to use for groups messaging} {GroupsMessagingModule} GroupsMessagingModule
MessagingModule = GroupsMessagingModule

;# {ServicesConnectorModule} {Module:GroupsModule} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector} XmlRpcGroupsServicesConnector
;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on
;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend
ServicesConnectorModule = XmlRpcGroupsServicesConnector

;# {GroupsServerURI} {Module:GroupsModule} {Groups Server URI} {}
;; URI for the groups services
;; e.g. http://yourxmlrpcserver.com/xmlrpc.php for Flotsam XmlRpc
;; or http://mygridserver.com:82/Grid/ for SimianGrid
GroupsServerURI = "http://virtcons.ru/sl/opengroups/xmlrpc.php"

;# {NoticesEnabled} {Module:GroupsModule} {Enable group notices?} {true false} true
;; Enable Group Notices
NoticesEnabled = true

;; This makes the Groups modules very chatty on the console.
; DebugEnabled = false

;; XmlRpc Security settings. These must match those set on your backend
;; groups service if the service is using these keys
; XmlRpcServiceReadKey = 1234
; XmlRpcServiceWriteKey = 1234

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

P.S. Как одельно поднять всё у себя, например, локально, я расскажу как-нибудь в другой раз, сейчас времени не особо ;(

воскресенье, 17 июня 2012 г.

[OpenSim] В грид!

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

Значится так: мы будем рассматривать только технический аспект подключения к гриду. То, что любой открытый грид - не SL, ваши личные трудности и проблемы, точно так же как и трудности любого грида, за исключением технических, лично меня не тревожат никоим образом. В принципе, лично мне нравится буржуинский «OSGrid» потому что там есть всё то же самое, что и в современном SL. Всё - это значит всё, нет только оголтелых адептов совкового менталитета, потому что те русские, кто есть, тщательно шифруются и правильно делают. Никакого «КП», никакого «Дома-3», тишь да благодать в этом плане. А вот населения хватает как такового, скучать не приходится.

Есть и отечественный грид - «OpenSim.ru», я в самой первой статье приводил ссылки на него. Этот грид мне откровенно жалко, потому что из населения одни боты So Hyun'a, правда, живущие полной жизнью и даже лабающие на музыкальных инструментах. Такого ни у кого нет, надо полагать :D К слову сказать, мой сим Kin-Dza-Dza стоит именно в этом гриде в настоящее время, да и островов там хватает, можете сами убедиться. Он хороший, но пока что нет войса, зато недавно появились группы.

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

Запомните раз и навсегда: если у вас динамический IP-адрес или же адрес все-таки статический, но провайдер решил «позаботиться» о вашей же безопасности и закупорил фаерволом все порты или, ещё хлеще, и то и другое вместе, то максимум что вы можете получить, так это строчку в этом печальном списке отъявленных «недоподключенцев». Чудес не бывает - если закрыты порты, никто никогда не сможет к вам подключиться, даже если у вас и неизменный IP-адрес, тем паче, если он, вдобавок ко всему, меняется от сессии к сессии. Севисы а-ля «DynDNS», конечно, решат проблему меняющегося адреса, но уж тогда лучше решать проблему комплексно и купить за $2/мес. (а у кого и дешевле) внешний адрес вкупе с открытыми настежь портами. Все остальные кустарные решения будут неизменно приводить к онанизму. Чудес не бывает.

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

Все предметы сим хранит в так называемых «ассетах». Логически это ничто иное, как записи в базе данных. Вопрос только - в какой именно. Если симулятор запущен, как standalone, то абсолютно всё хранится в локальных базах, если же сим находится в гриде, то всё, что находится на автатаре и в инвентаре хранится в базе грида, а вот то, что находится на симе - в базе сима. Но есть один нюанс. Всё зависит от настроек конкретного грида. Что там и как, знает только гридмастер. Таким образом, ассеты сима могут храниться и в базах грида совершенно запросто. Именно поэтому идем в консоль нашего сервера и печатаем очень простую команду:
  1. Region (Kin-Dza-Dza) # save oar /home/opensim/kin-dza-dza.backup.oar
Вообще архив делать нужно постоянно и как-нибудь я напишу, как этот процесс автоматизировать. А пока выключим сервер и пойдем конфиги править, чтобы подключиться к русскому гриду.

Если помните, я упоминал о глобальных координатах в гриде, поэтому еще раз проверьте при помощи карты, что они указывают на свободное место, затем просто берем в файле OpenSim.ini закомментируем конфиг одиночного режима и раскомментируем другой, для грида.
; Include-Architecture = "config-include/Standalone.ini"
    Include-Architecture = "config-include/Grid.ini"
После запуска сервера он будет подключен уже в грид и попасть на сим можно будет только с авторизацией грида, то есть с тем логином и паролем, с которым вы зарегистрировались у них на сайте.

четверг, 7 июня 2012 г.

[OpenSim] Терраформ

Ну вот, у нас есть четыре сима, настало самое время заняться их комплексным терраформированием, чтобы получить единое пространство. Как я уже говорил, я буду моделировать полуостров Крым, для чего иду в «Google Maps»:



Кстати, кое-какой терраформ можно выполнять и из консоли сервера. Для примера, давайте вместо лысых пятачков на всех четырех регионах сделаем одино большое и ровное плато. Для этого нужно из рута сервера отдать команду на терраформ:
  1. Переходим в корень:
    Region (Crimea1) # change region root
  2. Ровняем землю и поднимаем на уровень 30 метров (вода у нас по умолчанию на 20 метрах):
    Region (root) # terrain fill 30
И все, все четыре сима превращаются в одно большое пространство. Если же нужно с каким-то одним регионом проделать подобное, то... Думаю, вы уже догадались ;D



Итак, нас есть скриншот, который нужно переработать в битовую карту (RAW) террейна, понятную симулятору. Немного теории. Мы знаем, что регион имеет размеры 256х256 метров. Сетка высот кодируется raw-файлом, размерами 256х256 точек, таким образом получается, что одна точка кодирует высоту одного квадратного метра террейна. Значение точки может лежать в пределах от 0 до 255, что на практике дает нам цвет пикселя в градациях серого. Если это рассматривать в системе цветокодирования RGB, то получается, что мы имеем 4 канала цвета: R (красный), G (зеленый), B (синий) и A (прозрачный, альфа). Смотрите, как понимает значение этих каналов сервер, потому что если с красным и синим все более-менее понятно, то зеленый канал таит в себе чудеса:
  1. R (красный) Высота основания точки в метрах от 0 до 255
  2. G (зеленый) Множитель к высоте основания точки
  3. B (синий) Высота уровня воды (20 м по умолчанию)
Вычисляется окончательная высота точки по специальной формуле, описывающей взаимодействие красного и зеленого каналов карты, к счастью, несложной:
  1. Высота (канал R) * Множитель (канал G) / 128
Зачем так сделали и что хотели этим достичь, я не знаю, да и не очень хотелось бы знать. Большие знания - большие печали. Просто поступим так, как требуется, чтобы получить то, что мы хотим. Возвращаемся к нашему скриншоту и вырезаем квадрат, равный 512х512 пикселей (2х256, у нас же по два сима на одну сторону) с необходимой территорией внутри:



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



Ну вот, теперь у нас есть материал для терраформирования - установим значения каналов по 128, разрежем на четыре части эту картинку и... Здесь бы написать «и загрузим на сервер», да только обломитесь, девочки и мальчики. Не все так просто. Тут как в сексе - вроде бы ничего непонятного, все предельно ясно, но сноровка требуется :D Короче, разрезаем нашу картинку на четыре равные части и каждую сохраняем как 24-битную TGA, потому что дальше мы пойдем приводить их к общему знаменателю и удобоваримому виду. И вот на что обратите внимание особое - у меня не даром покрашен полуостров в серый цвет, а то место, где должно быть море - в черный. Помните теорию? Вот я таким образом явно разделил высоты.



Теперь немного пошарим по инету и скачаем вот что:
  1. «Terragen» - генератор ландшафтов.
Сегодня мы им воспользуемся для конверсии наших картинок, но вообще рекомендую ее освоить, потому что в ней можно делать весьма прикольные терраформы и потом все это барахло грузить в сим. В конце статьи, в качестве бонуса, я покажу терраформ горного участка местности с озерцами на те же четыре сима, сделанный в ней.
  1. «Bailiwick» - редактор каналов raw-файлов (требует для работы .Net 2.0).
Эта прога специально написана добрыми самаритянами, чтобы генерировать правильные файлы для SL из того шита, что в нее грузят такие деятели, как мы с вами. Так что ставим все это барахло, курим (программы под Win32, имейте в виду, если что, WINE вас спасет) и делаем четыре raw'чика для наших регионов.

А теперь внимательно следите за руками, кто прощелкает, у того дырки в земле будут! :D



Итак, берем «Terragen» и, немного поигравшись с ним, как же без этого, начинаем выполнять некие осмысленные действия. Сперва нажимаем кнопку «Import» (1) и в открывшемся окне (опять 1) выбираем первый из подготовленных загодя четырех картинок в TGA. Когда он загрузится, нажимаем кнопку «Modify» (2) И выставляем значения высот, зафиксировав их нажатием кнопки «Set Height Range». Я выбрал такие, как на скриншоте, у вас могут быть свои, определенные экспериментально. После настройки высот закройте это окошко кнопкой «Close», иначе все остальные окна будут неактивны. Затем установим необходимый уровень воды - у нас он равен 20 метрам, так как мы его не меняли на своих симах. Окно настроек воды открывается нажатием на квадратную кнопку слева с изображением волн. Значение воды также фиксируем.

Ну вот, основное сделано, теперь можно посмотреть предварительно, как все будет выглядеть. Сбоку на панельке есть большая квадратная кнопа «3D», жмем:



Там есть некое подобие левой руки 3D-камеры, можно посмотреть со всех сторон эскиз, но управление у нее абсолютно нечеловеческое. Впрочем, лучше, чем ничего. Теперь жмем кнопку «Save» (3) и сохраняем то, что у нас получилось, в формате террейна с расширением .ter.

Теперь берем другую софтину, «Bailiwick», и при минимуме телодвижений формируем RAW-файл, годный для сима. Импортируем, проверяем, что все в порядке, сохраняем уже как .raw, все. Стоит обратить внимание, что у этой программы также есть поле с указанием уровня воды. Так как он у нас стандартный, то мы ничего не делаем, если у вас свой, то нужно его перед сохранением изменить в этом поле.





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



По правде сказать, по уму надо бы еще поработать над рельефом, поскольку в Крыму есть горы, озера и т.п. Но перенос рельефа - это задача, производная от той, которую мы только что решили, стало быть, дело техники. Поэтому я бы вам порекомедовал самостоятельно поработать над этим и задать высоты в своих тераформах, хотя бы ради тренировки. Ну а сейчас обещанный результат работы «Terragen'a»:



Вот и все. Можно, конечно, сказать, что заморочено как-то все, проще по-старинке, in-world при помощи старых добрых Ctrl-5... Болтуны. Уж кто этими «старыми добрыми» что-то и терраформил, такой ереси точно не скажут :D

среда, 6 июня 2012 г.

[OpenSim] Что от нас скрывают в LindenLab

Знаю-знаю, я обещал рассказать, как подключить свой сим к гриду. Но давайте рассуждать здраво - ну вот вы подключили свой сим, позвали туда своих друзей (чтобы забанить, не иначе как ;D ), а у вас на симе - лысина суши торчит из воды и вы там, посередине, криво примостили свой аватар на кубик. В общем, скажут вам друзья "Круто!" из жалости и свалят обратно в SL лясы точить. Оно вам надо?

Сегодня я расскажу, как сделать правильный терраформ, попутно открою святую тайну всех эстейт-администраторов и то, что от вас скрывают от вас в LindenLab по поводу серверов и регионов. Об этом я уже упоминал в прошлой статье, сегодня же мы своими руками проделаем такие же манипуляции, какие проделывают Линдены, когда берут свою $1000 за установку сима очередному незадачливому клиенту.

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

Для этого, как всегда, расчистим лабораторный стол сделаем несколько подготовительных манипуляций. В прошлый раз мы запустили свой сим с одним единственным регионом, сегодня же мы будем создавать на этом сервере совершенно иную конфигурацию, поэтому будет разумно немного вернуться назад и создать необходимые нам регионы снова прямо из консоли сервера. Для этого мы идем в папку osim, где лежат файлы сервера и ищем там еще одну папку, которая называется Regions. Как можно догадаться, здесь лежат файлы, которые описывают конфигурацию всех наших регионов, которые размещены на сервере, ведь мы уже знаем, что один сервер может обслуживать количество оных числом более единицы.

В нашем случае интересующий файл будет один с интуитивно понятным названием Regions.ini, не перепутайте ;) Если мы его откроем, то увидим переменные, которые описывают те или иные параметры. Я сейчас приведу свой файл, в принципе, там все понятно, что для чего нужно:
[Kin-Dza-Dza]
RegionUUID = 6962ac4b-d8a5-4142-99b6-7dee1f6b0474
Location = 1000,1000
InternalAddress = 0.0.0.0
InternalPort = 9000
AllowAlternatePorts = False
ExternalHostName = 191.168.0.2
Теперь вы знаете, что почти все ответы на вопросы, которые задавал нам сервер, храняться именно здесь и если что, нужно идти сюда, чтобы что-нибудь поправить или поменять. Но мы к этому еще когда-нибудь вернемся, а пока просто переименуем этот файл во что-либо иное, например:
  1. $ mv Regions.ini Regions.ini.old
Все, возвращаемся в osim и запускаем сервер. Так как сервер не найдет нужного конфига во время старта, он опять начнет задавать нам все те же вопросы, которые были в прошлый раз. Отвечаем безо всякого стеснения, однако, помня о том, что на этот раз мы создаем не один, а четыре региона, названия будем давать такие, чтобы потом нам было удобно между ними переключаться. В конце концов их всегда легко поменять на любые другие, когда это станет нам нужно.

Лично я буду создавать модель моего родного края - полуострова Крым, поэтому буду называть регионы Crimea1, Crimea2, Crimea3 и Crimea4. Первый регион создаем не глядя, просто отвечаем на вопросы. Единственный момент, на который нужно обратить внимание - в какой-то момент сервер спросит, хотите ли вы разместить новый регион в существующем эстейте или нет.
New region name []: Crimea1
Region UUID [8b0c7f33-0e3b-4026-9407-25392fa316c0]: 
Region Location [1000,1000]: 
Internal IP address [0.0.0.0]: 
Internal port [9000]: 
Allow alternate ports [False]: 
External host name [SYSTEMIP]: media      
14:22:18 - [REGION LOADER FILE SYSTEM]: Loading config files from ./Regions
14:22:18 - [REGION LOADER FILE SYSTEM]: Loading config file ./Regions/Regions.ini
14:22:18 - [REGION LOADER FILE SYSTEM]: Loaded config for region Crimea1
14:22:18 - [LOAD REGIONS PLUGIN]: Loading specific shared modules...
14:22:18 - [LOAD REGIONS PLUGIN]: DynamicTextureModule...
14:22:18 - [LOAD REGIONS PLUGIN]: LoadImageURLModule...
14:22:18 - [LOAD REGIONS PLUGIN]: XMLRPCModule...
14:22:18 - [LOAD REGIONS PLUGIN]: Done.
14:22:18 - [LOAD REGIONS PLUGIN]: Creating Region: Crimea1 (ThreadID: 1)
14:22:18 - [ESTATE]: Region Crimea1 is not part of an estate.
Do you wish to join region Crimea1 to an existing estate (yes/no)? [yes]: no
Все дело в том, что сервер помнит, что у нас уже есть эстейт, и хочет знать, что именно мы сейчас создаем, дополнительный парсель или совершенно отдельный сим? Если ответить «yes», то будет создан новый парсель на существующем эстейте, а так как мы убрали информацию о старом, то это будет парсель на весь существующий сим. Так что в данном случае отвечаем «no» и жмем ENTER, после чего сервер спросит, как нужно назвать вновь создаваемый эстейт (сим то бишь), а затем назначить ему владельца вместо Test User (или оставить этого). Да-да, я помню, с владельцами непросто. Но пока этим пренебрежем и вальсируем дальше.

Следом создаем остальные эстейты. Здесь нам поможет команда сервера create region. Давайте посмотрим, как правильно нужно ее отдавать:
Region (Crimea1) # help create region
create region ["region name"] 
Create a new region.

The settings for "region name" are read from <region_file.ini>. Paths
specified with <region_file.ini> are relative to your Regions
directory, unless an absolute path is given. If "region name" does not exist
in <region_file.ini>, it will be added. Without "region name", the first region found
in  will be created. If <region_file.ini> does not exist, it will be created.
Мы видим, что нужно просто задать имя нового региона и, по необходимости, имя файла, в котором будут его настройки. Здесь тоже есть один нюанс - поскольку происхоит постоянная путаница с терминологией, то не всегда очевидно, что же мы делаем и что получим в результате. Запомните - эстейт это сим, регион же может быть как симом, так и парселем. Сейчас мы создаем четыре эстейта, на которых будет расположено четыре парселя (региона), размерами по целому эстейту на каждый. Кроме того, создавая эстейт, полезно переместиться из текущего региона Crimea1, как мы видим, написано в приглашении сервера, в корневую сущность. Сделать это можно простой командой:
Region (Crimea1) # change region root                       
Currently selected region is root
Если же вы создаете несколько эстейтов, внутри которых планируется разместить несколько регионов (парселей), то для каждого эстейта лучше всего назначать свой ini-файл. Для наглядности, давайте сейчас так и поступим, создадим для каждого эстейта свой ini-файл, в данном случае это будет Crimea2-Regions.ini:
Invalid command
Region (root) # create region Crimea2 Crimea2-Regions.ini
=====================================

We are now going to ask a couple of questions about your region.

You can press 'enter' without typing anything to use the default

the default is displayed between [ ] brackets.

=====================================

Region UUID [027a1195-f7bc-4610-9701-0f571c6d953a]: 
Region Location [1000,1000]: 1000,1001
Internal IP address [0.0.0.0]: 
Internal port [9000]: 9001
Allow alternate ports [False]: 
External host name [SYSTEMIP]: 192.168.0.2
14:39:31 - [ESTATE]: Region Crimea2 is not part of an estate.
Do you wish to join region Crimea2 to an existing estate (yes/no)? [yes]: no
New estate name [My Estate]: Crimea2
Здесь важно помнить, что нужно ему задать правильные координаты, правильный порт и правильное расположение - указать, что это новый эстейт, а не парсель в существующем эстейте. Вновь назначаем ему владельца и, вуаля!
14:42:21 - [GRID SERVICE]: Region Crimea2 (027a1195-f7bc-4610-9701-0f571c6d953a) registered successfully at 256000-256256
14:42:22 - [REGION]: Enabling logins for Crimea2
14:42:22 - [GRID SERVICE]: region Crimea2 has 1 neighbours
14:42:22 - [INTERGRID]: Informing 1 neighbours that this region is up
Обратите внимание на крайнее сообщение. Сервер нам говорит, что у нашего нового региона есть один сосед и он включен. Что ж, здесь теоретическая часть заканчивается и начинается практика - по аналогии создаем еще два региона и не забываем, что значение порта должно увеличиваться на единицу, да и координаты нужно указать таким образом, чтобы все четыре сима встали друг к дружке самым что ни на есть квадратно-гнездовым образом.



Теперь вам понятно за что Линдены дерут бабло? Если бы мы с вами были Линденами, мы бы уже положили себе в карман $4000 безо всякого зазрения совести ;) К слову сказать, точно так же поступают в LindenLab, когда вам впаривают туфту на тему «один сим - один сервер», сколько железный ящик бует тянуть вот таких виртуальных регионов, столько туда и впихнут, а в наши дни вообще оптимизация достигла перигелия - на железке запускается несколько виртуальных машин, которые через балансер... В общем, это уже совершенно другая история, которую я вам рассказывать не буду, поскольку это долго и нудно. Просто запомните - симов на одной машине можно запустить столько, сколько жадность и железо позволяет.