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

Немного технической части
  1. 4096 байт, содержащих оффсеты чанков (так называются блоки 16x16x128) и их размер в блоках по 4кб, округляя вверх, 3 байта оффсет, 1 — размер
  2. 4096 байт timestamp’ов чанков, по 4 байта на каждый
  3. Оставшееся место до конца файла — собственно, данные чанков, сжатые Zlib. 4 байта — размер сжатых данных, 1 — способ сжатия (по умолчанию 2, Zlib (RFC1950)), размер-1 запакованная злибом NBT-структура, т.е сам контейнер кубов
    Если упакованные данные занимают меньше целого числа секторов по 4 кб, то остаток сектора заполняется нулями, т.к каждый чанк должен начинаться с оффсета, выраженного целым числом секторов по 4096 байт
Выбор языка

Реализовать такую структуру можно на любом языке, я остановился Delphi 7. Во-первых, это пока единственный язык, который я знаю, во-вторых, именно на 7 версии года 4 назад я начинал писать блокноты по мануалам из Игромании.

Как копировать карты с сервера в майнкрафт в одиночный мир | WORLD DOWNLOADER | Установка | Обзор

Код

Так как данные хранятся в сжатом виде, нам необходим модуль zlib.
Я использовал ZlibEx

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

Tchunk = class(TObject) private public Data: tmemorystream; c_data: tmemorystream; c_stream: tzcompressionstream; constructor Create; procedure writeblock(x, y, z, block: integer); overload; procedure writeblock(x, y, z, block, color: integer); overload; procedure compress; end;

Код этого класса:

constructor tchunk.Create; begin Data := TMemoryStream.Create; Data.size := 82360; Data.LoadFromFile(‘data.bin’); c_data := TMemoryStream.Create; c_stream := tzcompressionstream.Create(c_data, zcdefault, 15, 8, zsdefault); end; procedure tchunk.writeblock(x, y, z, block: integer); begin Data.Seek(form1.getoffset(x, y, z) + 16487, 0); Data.Write(block, 1); end; procedure tchunk.compress; var buffer: array [0..82360] of byte; begin c_data.Position := 0; Data.Position := 0; Data.Read(buffer, 82360); c_stream.writebuffer(buffer, 82360); c_stream.Free; c_data.SaveToFile(‘file’ + IntToStr(n)); end;

Функция getoffset выдает нужое смещение по формуле y + ( z *128 + ( x * 128 * 16 ) )

function tform1.getoffset(x, y, z: integer): integer; begin Result := y + (z * 128 + (x * 128 * 16)); end;

Добавим в var пару переменных:

chunks:array[0..32] of array[0..32] of tchunk; n: integer=0;

Процедура для сборки всех чанков в готовый файл:

procedure tform1.SwapEndiannessOfBytes(var Value: cardinal); var tmp: cardinal; i: integer; begin tmp := 0; for i := 0 to sizeof(Value) — 1 do Inc(tmp, ((Value shr (8 * i)) and $FF) shl (8 * (sizeof(Value) — i — 1))); Value := tmp; end; procedure tform1.generatefile; var fileoffset: integer; time, compressiontype, counter: integer; filename: string; regionfile: tfilestream; tmp: cardinal; size: integer; n_x, n_z: integer; bu: array[0..99999] of byte; n: integer; roundedsize: integer; neededsize: integer; d: byte; begin fileoffset := 2; time := $d8de2f4e; compressiontype := $02; filename := GetVar(‘Appdata’) + ‘.minecraftsavesNewWorldregionr.0.0.mcr’; regionfile := tfilestream.Create(filename, fmcreate); n := 0; for n_x := 0 to 31 do for n_z := 0 to 31 do begin chunks[n_x][n_z].compress; roundedsize := ((chunks[n_x][n_z].c_data.Size) div 4096); if (((chunks[n_x][n_z].c_data.Size) mod 4096) > 0) then Inc(roundedsize); regionfile.seek((4 * ((n_x mod 32) + (n_z mod 32) * 32)), 0); tmp := fileoffset; SwapEndiannessOfBytes(tmp); tmp := tmp shr 8; regionfile.Write(tmp, 4); regionfile.seek(4 * ((n_x mod 32) + (n_z mod 32) * 32) + 3, 0); regionfile.Write(roundedsize, 1); size := chunks[n_x][n_z].c_data.Size + 1; regionfile.seek(fileoffset * 4096, 0); tmp := size; SwapEndiannessOfBytes(tmp); regionfile.Write(tmp, 4); regionfile.Write(compressiontype, 1); chunks[n_x][n_z].c_data.Position := 0; chunks[n_x][n_z].c_data.readbuffer(bu, chunks[n_x][n_z].c_data.size); regionfile.Writebuffer(bu, chunks[n_x][n_z].c_data.size); regionfile.seek((n) * 4 + 4096, 0); regionfile.Write(time, 4); fileoffset := fileoffset + ((chunks[n_x][n_z].c_data.Size) div 4096); if (((chunks[n_x][n_z].c_data.Size) mod 4096) > 0) then fileoffset := fileoffset + 1; Inc(n); end; neededsize := 4096 * fileoffset — regionfile.Size — 1; regionfile.Seek(regionfile.Size, 0); d := 00; for n := 0 to neededsize do regionfile.Write(d, 1); regionfile.Free; end;

Читайте также:  Как сделать резной песчаник в Майнкрафт

Всё, теперь мы имеем метод записи любого блока по любой координате, в пределах региона. При желании, несложно повторить то же для остальных регионов, надо строк 10 кода.

Обертка для writeblock:

procedure tform1.writeworld(x, y, z, block: integer); var xw, zw: integer; begin xw := (x div 16); zw := (z div 16); chunks[xw][zw].writeblock(x mod 16, y, z mod 16, block); end;

Генерация мира, его сжатие и сохранение.

procedure TForm1.Button4Click(Sender: TObject); var x, y, z: integer; xx, zz: integer; image: tbitmap; begin for xx := 0 to 31 do for zz := 0 to 31 do begin chunks[xx][zz] := tchunk.Create; end; image := tbitmap.Create; image.LoadFromFile(‘image.bmp’); for x:=0 to 127 do for y:=0 to 116 do begin if image.Canvas.Pixels[x,y]=clblack then form1.writeworld(x,117-y,0,49); if image.Canvas.Pixels[x,117-y]=clwhite then form1.writeworld(x,y,0,80); end; form1.generatefile;

Результат:
image
image

image

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

Проект можно скачать тут.

  • Невозможно сохранять изменения в сгенерированном регионе (возможно, из-за того, что пишется одинаковый timestamp, который не совпадает с временем последнего сохранения в level.dat, как разберусь с форматом последнего — попробую реализовать)
  • Спавн лучше переставить с помощью McEdit, т.к вполне возможно, что после генерации он окажется в сотне блоков над землей, что чревато летальным исходом(тоже можно менять в level.dat)
  • Нет генерации света, вместо этого освещены все блоки, даже под землей(Рассчет освещения — отдельная серьёзная задача, пока не готов ее решать)
  • Починить сохранение, т.к без этого теряется половина смысла
  • Сделать поддержку записи дополнительной инфы(цвет шерсти, листвы, ориентация печек, etc) // частично готово
  • Какое-то подобие ландшафта(холмы/дома/озера)
  • Доработал generatefile , сделал нормальный разворот
  • Форматирование кода
  • Наброски a dditional block data , см. в проекте, ссылка обновлена
  • Описание формата карт
  • ID блоков для функции writeblock/writeworld
  • Zlib для Delphi

Источник: habr.com

Как заново сгенерировать мир в minecraft на сервере

WorldRegenerator. Даёшь чистую карту!

WorldRegenerator. Даёшь чистую карту!

Пожалуй, одной из главных проблем игры-песочницы как Minecraft является состояние карты, которое постепенно ухудшается в связи с деятельностью игроков (добыча ресурсов). На приватных серверах дело обстоит получше: большая карта и малый поток игроков — износ карты происходит гораздо медленнее. Но у нас публичный сервер и карта износится быстро. Износ карты — одна из причин необходимости проведения вайпов. Ведь с изношенной картой сервер теряет привлекательность для новичков: где найти нужные ресурсы, если их выкопали другие игроки?

Читайте также:  Лагает когда смотрю на другого игрока Майнкрафт

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

WorldRegenerator. Даёшь чистую карту!

Вся суть столбостроительства.

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

С самого запуска первых серверов мы активно занимались такой чисткой, правда, это делалось вручную. А сейчас серверов стало много и размеры карт уже не те, что раньше — всё обойти нам не по силам. Можно конечно было назначить людей, которые бы этим занимались, но тут проблема в доверии и в их силах — а вдруг отрегенерируют то что не нужно?

Автоматика приходит на помощь
Поняв, что вручную нам такую работу не осилить, дело переходит к автоматике. Автоматизация является одним из направлений нашего развития — её задачей является снизить количество рутиной работы для нашей команды. Так было принято решение о разработке регенератора карты (потому что в свободном доступе их нет).

ploxo

Ещё полгода назад по нашему заказу была разработана первая версия регенератора. Но её работа не увенчалась успехом — по непонятным причинам он попросту зависал. Его код был сложен для понимания, поэтому проект был заморожен и сотрудничество с тем исполнителем, который нам его написал было прекращено (первая версия модификации Additional Blocks с кучей багов — тоже его заслуга).

smile

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

Все три последние дня мы обкатывали регенератор на каждом из наших серверов. Была проведена регенерация основного и нижнего миров. Было обработано порядка 750 000 чанков, процесс занял около 7 часов (на один сервер).

Что же такое регенерация?
Регенерация — процесс восстановления участков карты в первоначальное состояние. Под участками мы понимаем чанки и выбор на них пал не случайно. Дело в том, что незаприваченная часть карты имеет сложную форму — её нужно как-то «выделить».

Читайте также:  Как в Майнкрафте поставить квадратные скобки

Во-вторых, обработать всю карту целиком нельзя — сервер упадёт. Следовательно, приходится разбивать задание на порции и чанки здесь подошли в самый раз. Дело в том, что Bukkit API предоставляет возможность регенерации чанков. Да, именно чанков. Регенерировать конкретную область нельзя — только весь чанк целиком.

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

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

  • Поддержка карты в хорошем состоянии.
  • Делает сервер привлекательным для новичков в любое время — теперь нет проблем с поиском ресурсов.
  • Убирает дыры от карьеров и прочих механизмов, изменяющих ландшафт.

WorldRegenerator. Даёшь чистую карту!

Ещё мы сняли для Вас «кино», демонстрирующее работу регенератора.

Источник: redserver.su

MultiWorld — Переход между мирами. Как добавить другие миры на сервере Майнкрафт?

✔️ После изучение данного материала, Вы узнаете — «Как сделать переход между мирами на сервере Minecraft?». А поможет нам в этом плагин MULTIWORLD. Мы рассмотрим его основные функции и принцип работы, а также изучим главные команды. Приятного просмотра, друзья!

Инструкция по установке плагинов находится — ЗДЕСЬ.

Подробнее смотрите в нашем видео ролике:

✅ ПОДПИШИТЕСЬ НА НАШ YOUTUBE КАНАЛ ✅

❗️ ❗️ КАК ЗАКАЗАТЬ СЕРВЕР МАЙНКРАФТ СМОТРИТЕ — ЗДЕСЬ ❗️ ❗️

ПРОМО-КОД НА СКИДКУ 15%: ready-steady-go

Most Popular Articles

Citizens — как создавать ботов на сервере Майнкрафт? (настройка мобов, жителей, NPC, охранников, торговцев и квестов)

⭐️ ПРИВЕТСТВУЕМ НА HOSTING-MINECRAFT.RU⭐️ ✔️ Мы запускаем серию из 4-х видео роликов по созданию.

DeathMessages — сообщение после смерти игрока на сервере Майнкрафт.

⭐️ ПРИВЕТСТВУЕМ НА HOSTING-MINECRAFT.RU⭐️ ✔️ Ни для кого не секрет, что существуют десятки.

ImageMaps — настройка и обзор плагина. Как вставить любое изображение на свою карту в Майнкрафт?

⭐️ ПРИВЕТСТВУЕМ НА HOSTING-MINECRAFT.RU⭐️ ✔️ В сегодняшнем видео уроке мы расскажем Вам как.

Player Report — как жаловаться на игроков на сервере Майнкрафт?

⭐️ ПРИВЕТСТВУЕМ НА HOSTING-MINECRAFT.RU⭐️ ✔️ Являетесь администратором сервера? Тогда Вам просто.

SkinsRestorer — установка скинов на сервер Майнкрафт без лицензии.

⭐️ ПРИВЕТСТВУЕМ НА HOSTING-MINECRAFT.RU⭐️ ✔️ С помощью установки скинов Вы сможете изменить.

Источник: my.hosting-minecraft.ru