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

Помогите Как рисовать/писать на картах?

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

1. Рендерер. Собственно он и занимается рисованием.
Java:
package fromgate.dogtags;
 
import org.bukkit.entity.Player;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapRenderer;
import org.bukkit.map.MapView;
import org.bukkit.map.MinecraftFont;
 
public class DTRenderer extends MapRenderer {
 
    Dogtags plg;
    String text;
 
    public DTRenderer (Dogtags plg, String text){
        super (true);
        this.plg = plg;
        this.text =  text;
    }
 
    @Override
    public void render(MapView map, MapCanvas canvas, Player p) {
        // "обнуляем" карту
        for (int j = 0; j < 128; j++)
            for (int i = 0; i < 128; i++)
              canvas.setPixel(i, j, (byte) 0);
        // plg.dtimg - картинка (тип Image) загруженная из файла
        // если она существует - используем её как подложку
        if (plg.dtimg != null) canvas.drawImage(0, 0, plg.dtimg);
        // пишем текст строго по середине
        canvas.drawText(30, 63-(MinecraftFont.Font.getHeight()/2), MinecraftFont.Font, text);
        // пишем текст внизу карты
        canvas.drawText(2, 127-MinecraftFont.Font.getHeight(), MinecraftFont.Font, "§54;(с)2012, fromgate");
    }
}



В плагине, процедура создания новой карты (возвращает значение data предмета. Т.е. если вернуло 5, то просмотреть карту можно посредством /i map:5)
Java:
    public int createMap(Player p, String text){
        MapView map = Bukkit.getServer().createMap(p.getWorld());
        DTRenderer mr = new DTRenderer (this, text);
        mr.initialize(map);
        // Удаляем стандартные рендереры
        map.getRenderers().clear();
        // Назначаем наш
        map.addRenderer(mr);
        return map.getId();
    }

Теперь собственно можно создать карту при помощи команды:
createMap (player, "map test");
Где player - это игрок.
 
Ну и соответственно если у вас несколько типов карт, нужно либо писать несколько рендереров либо же создавать универсальный, который в зависимости от параметров рисует то что нужно.

Да, и картинку я готовил заранее: 128х128, соответствующая палитра. "Любую" картинку подсовывать пока не пробовал.
 
Обнаружился ещё один нюанс. Карты... обнуляются после рестарта. Поэтому сделал процедурку, которая обновляет карту. Т.е. переназначает ей рендерер заново. Вызываю в onEnable задаю в качестве параметров сохраненные в файл значения id карты и текст, который на карте пишется.

Java:
    public void updateMap(short id, String txt){
        MapView map = Bukkit.getServer().getMap(id);
        DTRenderer mr = new DTRenderer (this, txt);
        mr.initialize(map);
        for (MapRenderer r : map.getRenderers()) map.removeRenderer(r);
        map.addRenderer(mr);
    }
 
Карты... обнуляются после рестарта.
Это даже плюс, ибо количество карт ограничено, а так можно пересовывать только те карты, которые нужны, а остальные помечать как свободные
 
makkarpov, я не правильно выразился. Обнуляется изображение. Почему-то изображение нарисованное моим рендерером не сохраняется в файл карты :(
И чтобы не создавать новую карту - нужно апдейтить старую. Но если выясню как сохранять, апдейт карты будет не нужен...

С картами же вообще бодяга странная. Свободных карт по сути не бывает. Есть "утерянные". Допусти сделал игрок карту (id 0) и уронил её. Она деспавнилась. Другой игрок сделал карту карту (id 1). В этом случае есть вероятность, что он получит пустую карту, на которой будет нарисовано id 0, а после правого клика картой она сменит свой номер на 1 будет нормально работать. Новая карта всегда будет иметь номер равный текущему количеству карт. Деспавнутые карты, к сожалению не замещаются. Хотя вроде было бы логично...
 
Кстати, добавлю. Изображение обнуляется потому, что не происходит записи в NBT. Стандартный рендерер, насколько я помню, этим и занимается. Загружает изображение из NBT, меняет его (если есть изменения). И сохраняет обратно.

С этим можно бороться несколькими способами (Я ещё не пробовал, потому рассуждают теоретически).
1. Не удалять стандартные рендереры. Смещать координаты карты и надеяться, что Ваша картинка сохранится вместе с картой.
2. Сохранять изображение самому. Так работать будет точно.
 
Кстати, добавлю. Изображение обнуляется потому, что не происходит записи в NBT. Стандартный рендерер, насколько я помню, этим и занимается. Загружает изображение из NBT, меняет его (если есть изменения). И сохраняет обратно.

С этим можно бороться несколькими способами (Я ещё не пробовал, потому рассуждают теоретически).
1. Не удалять стандартные рендереры. Смещать координаты карты и надеяться, что Ваша картинка сохранится вместе с картой.
2. Сохранять изображение самому. Так работать будет точно.
DPOH-VAR вроде бы как копался в NBT.
 
DPOH-VAR вроде бы как копался в NBT.
Да, копался.
Я не трогал карты map_#.dat, но уверен, что там все просто.
Вот описание содержания файла: http://www.minecraftwiki.net/wiki/Map_Item_Format
Редактировать его вручную очень просто:
есть класс NBTCompressedStreamTools, который загружает гзипнутый файл и представляет его в виде NBTTagCompound. Далее все по инструкции.
Сложность заключается в том, что тут картинка сохраняется попиксельно, каждый цвет кодируется одним байтом => нельзя применить обычный рендер и скорее всего придется писать свой. (насколько понял - у карт есть всего несколько ключевых цветов по 4 градаций)
Как взять NBT теги после рендеринга - я еще не разобрался. Скорее всего помогут методы a(NBTTagCompound) и b(NBTTagCompound) у класса WorldMapBase. Один из них нужен для загрузки данных, другой для выгрузки. (предполагаю, что b - для получения объекта, a - для рендеринга). Тогда возможно получится использовать обычный рендер, а затем полученный тег сохранять в файл.
 
DPOH-VAR, там все просто, я копался в исходниках craftbukkit и убедился ;). Даже если не понимать, что там делается - можно тупо скопировать ;)
Я просто не нашёл причин, для чего мне это действительно нужно - сохранять в картах. Лишняя работа.
 

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

Назад
Верх