Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите Поблочное копирование (с использованием API WorldEdit и без)

AndreyF

Активный участник
Баллы
63
Извините, что пишу сюда, просто некуда было еще написать.
Обнаружил, что WE справляется с копированием блоков из модов, даже с копированием компьютеров.
Мне нужно сделать поблочное копирование, поэтому WE API не вполне подходит. Пытался найти копирование в исходниках WE, но ничего там не понял.
 
@AndreyF, вынесу Ваше сообщение в отдельную тему.

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

Если же нужно поблочное копирование, то в принципе все просто.
Перебирайте блоки области в цикле, определяете куда нужно копировать блок, выполняете target.setTypeIdAndData(source.getType(),source.getData(),false); (где target - куда копируем, source - откуда).
 
На самом деле не совсем понятно что требуется.
AndreyF, быть может расскажете в чем заключается изначальная задача?
 
На самом деле не совсем понятно что требуется.
AndreyF, быть может расскажете в чем заключается изначальная задача?
Как я понял человек хочет реализовать что то типа copy-paste для одного блока, а ответ уже дал fromgate
 
Спасибо конечно за помощь, но до того что предложил @fromgate я додумался сразу. Такой способ не скопирует, например, надпись на табличке, память компьютера (из мода) и т.д.
Мне нужно скопировать не только id и data блока, но и данные Tile entity.
Сейчас использую WE примерно так:
Код:
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
и т.д.
 
WorldEdit we = ((WorldEditPlugin) Bukkit.getServer().getPluginManager().getPlugin("WorldEdit")).getWorldEdit();
LocalWorld world = we.getServer().getWorlds().get(0);
Vector v1 = new Vector(координаты копируемого блока);
Vector v2 = new Vector(координаты куда копируем);
BaseBlock block1 = world.getBlock(v1);
world.setBlock(v2, block1, true);

Все копируется, но хотелось бы обойтись без WE.
 
Все копируется, но хотелось бы обойтись без WE.
Кроме информации id:data, в игре имеются также дополнительные объекты - TileEntity. Они содержат всю дополнительную информацию о блоке, например текст с таблички, инвентарь сундука и т.д. Данные о каждом TileEntity легко преобразовываются в NBT формат
Я думаю, подойдет такой способ копирования:
* Сначала выполнить set id and data
* Затем прочитать все NBT теги из оригинального блока
* Применить эти теги к только что созданному блоку. НО! кроме тегов x, y, z. Их нельзя заменять!
Потребуется использование CraftBukkit API, который зависит от версии сборки.
 
@DPOH-VAR, слушай, получается, что у блока тоже есть NBT-теги, куда можно писать все что угодно?
 
@DPOH-VAR, слушай, получается, что у блока тоже есть NBT-теги, куда можно писать все что угодно?
На самом деле не так. NBTесть не у блоков, а у TileEntity. Можно сказать, что это "особые" блоки.
И еще одно: стандартные методы взять/установить тег вводят ограничение на его содержимое. Например, у блоков нельзя поменять тег id, и всем стандартным блокам нельзя приписать дополнительные неизвестные теги (не знаю насчет модов) т.к. данные хранятся внутри уже не в виде нбт, а в виде значений полей объекта.
Насчет "писать что угодно" - можно писать что угодно в предметы. И еще как-то странно ведет себя SpawnPotentials.Properties у спавнеров - принимает все что угодно, но делает проверку каких-то значений входящего тега. В случае несоответствия шаблону - крашит карту или сервер.

Я забыл уточнить, что если блок не является TileEntity, то можно остановиться на копировании id и data. Но думаю, что это уточнение было бы лишним ;-)
 
@DPOH-VAR, я просто мыслю в таком направлении. Мне нужно сохранять дополнительные данные по карте применительно к блоку. Точнее даже к координатам x,z. Сохранять отдельно - не очень хотелось бы. Я думал, если можно задавать NBT для любых блоков, то меня как раз бы устроил слой бедрока при y=0 :) Но раз это только для TileEntity, то не подходит.
 
@yar1k, Вы ведь просто хотите данные записать, а потом считать? Лучше использовать для этого уже готовый формат (и соответственно механизмы для работы с ним) - yml.

Спасибо, но я не понимаю, как обратно выгрузить из yaml? Мне никогда не приходилось с ним работать, так как в .net с ним не работают. Помогите пожалуйста еще чуток :)
 
Слушайте, может кто скинуть пример кода с редактированием этих самых NBT-тегов?
 
@ql_Nik_lp,
Прочитать теги:
TileEntity tile1 = craftWorld.getTileEntityAt(x1,y1,z1); // берем плитку
NBTTagCompound compound = new NBTTagCompound(); // создаем пустой NBT тег
if (tile1 == null) return; // проверка обязательна, но можно структурировать по другому
tile1.b(compound); // загружем в тег все данные с плитки
Записать теги:
TileEntity tile2 = craftWorld.getTileEntityAt(x2,y2,z2); // берем другую плитку
if (tile2 == null) return; // опять же проверка
tile2.a(compound); // загружаем в плитку данные с тега.
Замечания:
- Нельзя заменять теги x,y,z. Это приведет к неработоспособности самого блока.
- Игрок просто так не увидит изменения блока. Для этого нужно сгенерировать новый сетевой пакет и отправить ему в принудительном порядке:
EntityPlayer.playerConnection.sendPacket(tile2.getUpdatePacket());
- CraftWorld мы получаем простым приведением от World
CraftWorld craftWorld = (CraftWorld) world;
- EntityPlayer мы получаем из craftPlayer.getHandle(); а самого СraftPlayer - приведением от Player

Могу поделиться своими исходниками, но я там делал все другим методом, через рефлексии.
 
@DPOH-VAR, спасибо.
Возникла проблема – при замене блока сундука или другого контейнера на другой блок, из него вылетают все предметы. Получается, что написанная вами последовательность действий не совсем правильна.
Как правильно заменить блок, имеющий TileEntity, на другой блок?
 
@DPOH-VAR, спасибо.
Возникла проблема – при замене блока сундука или другого контейнера на другой блок, из него вылетают все предметы. Получается, что написанная вами последовательность действий не совсем правильна.
Как правильно заменить блок, имеющий TileEntity, на другой блок?
Знакомя проблема, в своё время так и не решил, @DPOH-VAR тоже сразу не смог помочь. Так и не закончили плагин общими "усилиями". Тег у блока как-бы изменяется, но все предметы почему-то вылетают рядом с сундуком...
 
Знакомя проблема, в своё время так и не решил, @DPOH-VAR тоже сразу не смог помочь. Так и не закончили плагин общими "усилиями". Тег у блока как-бы изменяется, но все предметы почему-то вылетают рядом с сундуком...
Быть может имеет смысл покопаться в исходниках WE и посмотреть как он копирует все?
 
Быть может имеет смысл покопаться в исходниках WE и посмотреть как он копирует все?
Гиблое дело копать такую тонну чужого кода. В таких больших плагинах искать что-то одно - это как собирать лего из миллиона деталей)

Дождемся знающего человека, возможно он нашел решение ;)
 
@DPOH-VAR, спасибо.
Возникла проблема – при замене блока сундука или другого контейнера на другой блок, из него вылетают все предметы. Получается, что написанная вами последовательность действий не совсем правильна.
Как правильно заменить блок, имеющий TileEntity, на другой блок?
Да, при замене полного сундука другим блоком, его содержимое выпадает. Но я не думал, что это проблема.
Добавим тогда еще один пункт, в начале:
Перед заменой, если BlockState целевого блока является InventoryHolder'ом - почистить его инвентарь.
Или более хардкорный способ: полностью очистить его NBT (т.е. установить пустой) - метод может быть полезен для модов с нестандартными блоками.
UPD:
Быть может имеет смысл покопаться в исходниках WE и посмотреть как он копирует все?
Там черт ногу сломит. Код WE хорошо структурирован, но автор явно не задумывался о том, что его код кто-то будет читать.
 
Там черт ногу сломит. Код WE хорошо структурирован, но автор явно не задумывался о том, что его код кто-то будет читать.
Ну что есть, то есть :D
Однако если б я его не изучал, то до сих пор бы сидел без плагина "почанкового" выделения :)
 

Поделиться этой страницей

Назад
Верх