View file READ_ME_AUTHOR.txt

File size: 11.99Kb
Амулет Дракона. Многопользовательская WAP игра.

Версия 0.47

http://blade.fklab.com, http://wap.computermag.ru
[email protected]

ВНИМАНИЕ! Все права на данную игру, игровой мир и ролевую систему, а также на исходный код принадлежат Blade ([email protected]). Вы можете разместить игру на своем сервере только для некоммерческого использования, а также свободно дорабатывать и изменять исходный код при условии сохранения авторских прав и размещения на главной странице игры (где есть ссылки Войти, Регистрация) ссылки на сайт http://wap.computermag.ru со следующим названием: "Официальный сайт игры: wap.computermag.ru".


ИНСТАЛЛЯЦИЯ:
1. Скопируйте на свой хостинг, поддерживающий PHP все файлы (обязательно).
2. Переименуйте 1.htaccess в .htaccess (не обязательно, но иначе любой сможет скачать ваши файлы с сохраненной игрой).
3. Измените пароли в game.php ($admin), а также в forum.php ($admin_login) на свои (желательно)
4. Задайте пароль $gm_id в game.php для администрирования игры (просмотр и изменение данных игроков и т.д.). (не обязательно, пустой пароль по умолчанию считается недействительным). Внимание! Держите этот пароль в секрете, иначе тот кто его узнает сможет получить поный доступ к вашему сайту!
5. Установите на папке с игрой (там где лежит файл game.php) права доступа, позволяющие PHP скриптам создавать в этой папке свои файлы (не обязательно, но иначе игра может не работать). Если заходите на FTP из Internet Explorer, то в нем щелкните над папкой правой кнопкой мыши и поставьте все 6 галок. Я не уверен, что нужно именно все 6, может это открывает слишком большие права и какие-нибудь дыры на ваш сайт, так что лучше напишите письмо админам своего хостинга и уточните. 
6. Зайдите в игру и создайте первый аккаунт с логином admin и любым паролем. На основном экране в игре появится новая ссылка, где можно в любой момент воскреситься, стать бессмертным или телепортироваться в любую локацию.
7. Если с МТС и Билайна при открытии WAP страниц выдается что-то вроде: "Тип данных не поддерживается", "Слишком большой размер", "Ошибка 416" и т.д., то отключите на сервере автоматическую перекодировку в windows-1251 (админы должны знать как это делается - только правкой php.ini, файл .htaccess не поможет). Если регистрация нового игрока не работает, проверьте права доступа на папке с игрой, см. выше.

ФАЙЛЫ ИГРЫ:
game.php 	- основной файл
*.dat		- дополнительные файлы с PHP кодом
f_blank.dat	- бланк чистого мира, где определены все предметы и респавны монстров.
f_speakall.dat	- все диалоги всех NPC.
game.dat	- файл, где сохраняется весь игровой мир и все онлайн игроки. загружается при каждом обновлении wap страницы
loc_offline.dat	- файл со всеми оффлайн игроками, загружается только при логине или новой регистрации
flag_update	- если есть этот флаг, то все пользователи получают сообщение "Игра обновляется, зайдите через несколько минут". Используйте при обновлении файлов игры, чтобы игроки случайно что-нибудь не перезаписали.
flag_debug	- если есть этот файл, то в игру можно играть через Internet Explorer (для тестирования, выводится дополнительная информация, но ссылки не все, нужно смотреть исходный код страницы, так как WML отличается от HTML).

ВНИМАНИЕ! 
Иногда в игре стираются аккаунты игроков. Причина неизвестна, скорей всего это связано с сохранением и загрузкой локаций, см. ниже раздел про известные баги.

ОБСЛУЖИВАНИЕ:
1. Чтобы уменьшить размеры сохраняемых файлов, игра раз в 12 часов удаляет неактивные аккаунты: всех кто за 2 дня не повысил свой опыт, а также всех кто в течении двух недель не заходил в игру.
2. Откройте в Internet Explorer game.php?gm=XXX, где XXX - пароль $gm_id, который вы задали в game.php. В этом режиме можно смотреть и менять любые данные в игре (включая аккаунты игроков). Здесь же можно установить или убрать файл flag_update (ссылка вверху "set flag"), чтобы временно запретить дсотуп игрокам к игре. Внимание! Все это делается через функцию eval, поэтому если злоумышленник узнает ваш $gm_id, то это будет равносильно тому, как будто он может размещать свои PHP скрипты на вашем сервере, а значит получит доступ ко всем файлам и т.д.

ИСТОРИЯ
Вначале я создал небо и землю... гм, не то... вначале был один ассоциативный массив со всеми данными игрового мира и единственный game.php, который этот массив обрабатывал. Причем на диск этот массив сохранялся с помощью сериализации serialize(). В массиве можно было изменять что угодно, добавлять новые подмассивы, удалять элементы и т.д., а сохранялось все автоматически. Это было замечательно - у каждого объекта были события, например, у NPC on_die, on_speak и т.д., а у предметов on_take, on_use, on_drop и т.д. И этим событиям можно было назначать любую строку с php кодом, который исполнялся через eval() так, будто эта строка была в самом коде game.php! Это позволяло творить все что угодно - квесты, на лету в редакторе добавлять новые свойства предметам, создавать заклинания, новых монстров и т.д., просто напросто написав соответствующий код в строке on_use у предмета и не трогая базовый game.php.

Но выяснилась одна неприятная особенность сериализации - уж больно большие получаются файлы сохраненок игры: чистый бланк мира 400 кб, плюс сама игра game.php 130 кб. А так как при каждой загрузке wap страницы оба эти файла (сохраненка и game.php) читались с диска и обрабатывались заново, то это была большая нагрузка на сервер (на локальном селероне 300 в пике 100%). Поэтому главной целью стало уменьшить размер файлов.

Первым шагом оптимизации было изменение формата хранения данных - родственные элементы объединялись в одну строку с разделителем "|" с помощью implode(): $item = "Записка|1|100". Здесь в одной строке объединены название предмета, его количество (1 записка) и цена одной штуки (100 монет). В самой игре эта строка преобразовывалась в массив с помощью $item=split("\|",$item). Теперь цена была $item[2].

Вторым шагом стало разбиение кода на подгружаемые модули, а в сохраненке хранение только меняющейся информации. Все описания локаций и магии, разговоры и т.д. были вынесены в отдельные файлы, которые если надо подгружались с помощью eval(implode('',file("f_filename.dat"))). После такой строчки все содержимое файла как бы страивалось в текущую позицию скрипта. Таким образом удалось сохраненку мира без игроков сделать 40 кб, и сам скрипт game.php тоже 40 кб, а также в несколько раз снизить нагрузку на сервер - на селероне 300 в пике не более 40%.

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

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

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

1. Уменьшить размер сохраненки и основного скрипта, для чего параметры объектов объединять в одну строку, разделяя символом "|". Может быть даже любой объект в игре кодировать одной строкой (затраты на вычисления на порядок меньше, чем на загрузку файлов с диска).
2. Почитать статью "Оптимизация PHP" на http://php.spb.ru и оптимизировать код (выигрыш будет до 70%): вынести array_keys() за пределы foreach(), переменные за пределы строк, имена переменных сделать не более 5 символов и т.д.
3. Сделать удобный редактор, позволяющий добавлять новые локации, предметы и диалоги у NPC.

Есть три способа не загружать локации при каждом обращении к игре: shared memory (считает очень глючным, будут пропадать локации и персонажи, в Windows не работает), MySQL HEAP (много ограничений вроде на длину строки и т.д.) и socket server (требует поздние версии PHP, довольно сложно в обслуживании, надо устранить подгрузку модулей игры с PHP кодом).


КАК РАБОТАТЬ С МАССИВАМИ В PHP

Если открыть в Internet Explorer адрес типа game.php?gm=xxx, где ххх - это ГМ пароль, кот. задается в game.php, то можно получить доступ ко всей игре (точнее, к массиву игры). Кнопка View покажет значение того, что введете в поле ввода, а кнопка Eval выполнит то что введете как код PHP (с помощью функции eval()). При этом не нужно самому заходить в игру, а если щелкните по ссылке "set flag", то все игроки будут ждать, пока вы этот флаг не удалите (по ссылке "delete flag").
Добавление подмассивов или присвоение значений: допустим, у вас есть $game["test"]. Просто пишите $game["test"]["new"]="hello"; После такой строчки будет автоматически создано новое значение "test", равное "hello". Т.е. просто присваиваете что надо и не беспокоитесь о создании массивов и т.д. Да здравствует PHP!
Чтобы удалить массив или любой его элемент, используйте unset($game["test"]["new"]); Это удалит элемент "new" у массива "test". Чтобы удалить и сам "test", пишите: unset($game["test"]); Все очень просто.

ИССКУСТВЕННЫЙ ИНТЕЛЛЕКТ

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

Тип объектов в игре определяется названием и делятся на игроков (начинаются на "user.", например: user.xxx), добрых NPC (npc.xxx), стражу (npc.guard.xxx), монстров (npc.crim.xxx) и предметы (item.xxx). Предметы делятся на оружие (item.weapon.ххх), еду (item.food.xxx) и т.д., см. ниже в _SDK.txt.

Дальше смотрите описание типов объектов в _SDK.txt и шаблоны предметов в _templates.txt. Все остальные описания скиллов, магии, диалогов и т.д. где-то по файлам. В f_blank.dat лежит основа игровоко мира со всеми NPC, предметами и респавнами. Этот файл используется, если еще нет ни одной сохраненки.


Удачи!


ИЗВЕСТНЫЕ БАГИ:
1. при использовании боевой магии в f_usemagic.dat когда при эмуляции $war задаются параметры атакующего заклинания, опыт ставится 0, а т.к. после смерти в f_kill.dat это значение умножается на другое для проверки, не пора ли получить новый уровень, то там всегда 0 и поэтому если убить кого-то магией, то сразу дается одно очко опыта. Как исправить: взять значение exp из реального war игрока
2. при любых перемещениях предметов нет проверки на выход из диапазона целых чисел. а так как PHP самостоятельно в таком случае преобразует целое в тип float, то можно с двух монет поднять несколько миллиардов. Как исправить: проверять количество предметов след. образом: $count=intval($count); if (gettype($count)!="integer") die("Недопустимое число!");)
3. в начале игры даются 400 монет. игроки регистрируют множество персонажей, забирая у них начальные 400 монет. Как исправить: не давать денег вообще, но первые два очка сделать обучение бесплатным.
4. иногда при сохранении происходит неправильная сериализация (для сериализованной строки в виде s:xx:"yyy"; длина строки xx не соответсвует реальной длине строки yyy) и массив загружается пустым. можно исправить так: сделать функцию, которая попробует исправить строку: function calcser($s) {return "s:".strlen($s).":\"".$s."\";";} и если не удалось загрузить массив, то обработать загруженную из файла строку $s так: $s=preg_replace('/s:(?:\d+):"(.*?)";/e',"calcser('\\1')",$s); После чего попробовать еще раз использовать unserialize().
5. надо запретить регистрацию логинов с русскими буквами, иначе такие становятся "призраками" (в зав. от телефона) - на них никто не может напасть и посмотреть инфу, а они могут нападать на любого.