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

Небольшой совет: как ставить блоки с оглядкой на приваты...

fromgate

Старожил
Пользователь
Баллы
173
Имя в Minecraft
fromgate
Сейчас переписываю один плагин наткнулся на процедуру в коде, которую помню выстрадал за несколько дней с помощью знатоков с буккита.

Суть в чем. Если Ваш плагин должен ставить блок и при этом необходимо проверять может ли игрок (по команде которого) ставить эти блоки в данной местности: вдруг территория запривачена, это вообще спавн и т.п.
Очень часто авторы плагинов начинают теребить API Towny, Factions и т.п. плагинов. Я покрайней мере неоднократно такое встречал.
А на самом деле всё достаточно просто. Нужно установку блока выполнять не просто вызовом метода block.setType(....), а иницировать обработку события по установке блока. Т.е. чтобы поставить надо поставить блок, вызывать событие, которое обрабатывается всеми плагинами которые участвуют в процессе и если хоть один из них отменит обработку - состояние блока меняем на исходное.

Для чего это нужно. Допустим Ваш плагин строит башню. Приходит игрок в чужой двор/город/дом и строит там башню -если используется обычный setType без каких-либо проверок на приват. При этом! LogBlock и прочие "следящие" плагины не отлавливают это событие. Т.е. админы даже не смогут грифера отловить.

В общем, процедура тут. Возвращает true/false в зависимости от того удалось ли установить блок или нет.

Код:
    public boolean PlaceBlock(Location loc, Player p, Material newType, byte newData, boolean phys){
        return PlaceBlock (loc.getBlock(),p,newType,newData, phys);
    }
   
    public boolean PlaceBlock(Block block, Player p, Material newType, byte newData, boolean phys){
        BlockState state = block.getState();
        block.setTypeIdAndData(newType.getId(), newData, phys);
        BlockPlaceEvent event = new BlockPlaceEvent(state.getBlock(), state, block, p.getItemInHand(), p, true);
        this.getServer().getPluginManager().callEvent(event);
        if (event.isCancelled()) state.update(true);
        return event.isCancelled();
    }

P.S. первая процедура в списке добавлена для удобства, чтобы не вызывать в коде каждый раз loc.getBlock()

P.P.S. Эту процедуру можно применять и для "разбития" блока - замены на 0. Но я бы рекомендовал всё же тогда сделать аналог под BlockBreakEvent - во первых, мало ли какие плагины могут быть на сервере и правила приватов: обычно если запрещено строить, то запрещено и ломать. Но вдруг где-то реализованы что-то, что мы пока не можем предусмотреть, поэтому лучше сразу инициировать верное событие. Ну и плюс, можно попытаться порулить дропом в этом случае.
 
Как думаете, это сложно прикрутить к БилдКрафту и его строителям? И кто нибуть вообще пробовал организовать взаимодействие между modloader и bukkitAPI?
 
Как думаете, это сложно прикрутить к БилдКрафту и его строителям? И кто нибуть вообще пробовал организовать взаимодействие между modloader и bukkitAPI?

А разве ребята с mcports не прикрутили модлоадер к буккиту ?
 
DaleMartinWatson, никаких идей по этому поводу. Я вообще не видел что из себя представляют моды на буккит (я даже не видел индастриал крафта и билд крафта в принципе ;)). По логике, они должны обеспечивать совместимость с API (метод setType тогда должен поддерживать стандартные типы). Но как оно на практике...
 
А разве ребята с mcports не прикрутили модлоадер к буккиту ?
Прикрутили, но я не интересовался написанием модов и не знаю можно ли в них использовать BukkitAPI. А buildcraft для всех установок использует одного поддельного пользователя из-за этого на большинстве серверов его запрещают. Надо будет покопать в этом направлении, благо исходники открыты в отличии от industrial craft в котором тоже есть подобная проблема.
 
Сейчас переписываю один плагин наткнулся на процедуру в коде, которую помню выстрадал за несколько дней с помощью знатоков с буккита.

Суть в чем. Если Ваш плагин должен ставить блок и при этом необходимо проверять может ли игрок (по команде которого) ставить эти блоки в данной местности: вдруг территория запривачена, это вообще спавн и т.п.
Очень часто авторы плагинов начинают теребить API Towny, Factions и т.п. плагинов. Я покрайней мере неоднократно такое встречал.
А на самом деле всё достаточно просто. Нужно установку блока выполнять не просто вызовом метода block.setType(....), а иницировать обработку события по установке блока. Т.е. чтобы поставить надо поставить блок, вызывать событие, которое обрабатывается всеми плагинами которые участвуют в процессе и если хоть один из них отменит обработку - состояние блока меняем на исходное.

Для чего это нужно. Допустим Ваш плагин строит башню. Приходит игрок в чужой двор/город/дом и строит там башню -если используется обычный setType без каких-либо проверок на приват. При этом! LogBlock и прочие "следящие" плагины не отлавливают это событие. Т.е. админы даже не смогут грифера отловить.

В общем, процедура тут. Возвращает true/false в зависимости от того удалось ли установить блок или нет.

Код:
    public boolean PlaceBlock(Location loc, Player p, Material newType, byte newData, boolean phys){
        return PlaceBlock (loc.getBlock(),p,newType,newData, phys);
    }
 
    public boolean PlaceBlock(Block block, Player p, Material newType, byte newData, boolean phys){
        BlockState state = block.getState();
        block.setTypeIdAndData(newType.getId(), newData, phys);
        BlockPlaceEvent event = new BlockPlaceEvent(state.getBlock(), state, block, p.getItemInHand(), p, true);
        this.getServer().getPluginManager().callEvent(event);
        if (event.isCancelled()) state.update(true);
        return event.isCancelled();
    }

P.S. первая процедура в списке добавлена для удобства, чтобы не вызывать в коде каждый раз loc.getBlock()

P.P.S. Эту процедуру можно применять и для "разбития" блока - замены на 0. Но я бы рекомендовал всё же тогда сделать аналог под BlockBreakEvent - во первых, мало ли какие плагины могут быть на сервере и правила приватов: обычно если запрещено строить, то запрещено и ломать. Но вдруг где-то реализованы что-то, что мы пока не можем предусмотреть, поэтому лучше сразу инициировать верное событие. Ну и плюс, можно попытаться порулить дропом в этом случае.

От тебя я такого не ожидал... Первая идея как проверятиь приваты как раз и была - вызывать события...
Никогда бы не подумал, что это проблема... Правда есть ещё NoCheat и ему подобные, которые запрещают массированные события.
 
От тебя я такого не ожидал... Первая идея как проверятиь приваты как раз и была - вызывать события...
Никогда бы не подумал, что это проблема... Правда есть ещё NoCheat и ему подобные, которые запрещают массированные события.

В смысле? Чего не ожидал? Что я сделаю подлость и выложу процедуру на всеобщее обозрение? ;)
Я её писал когда-то давно. И тогда действительно её выстрадал: уж не помню чего я делал не так, но всё никак не мог заставить её как надо.

А выложил процедуру для того, чтобы упростить людям жизнь: многие начинают выискивать API во всяких "защитных" плагинах и проверять не защищен ли блок кем-то из них. У меня помню выпрашивали API для RoadProtector'а -- я когда глянул в то, куда он добавился, то ужаснулся. Там была поддержка Towny, LWC, Factions и ещё какой-то фигни. Ну и RoadProtector :)
А ведь все фактически меняется на вот эту (или схожую процедуру) процедуру.

Кстати, опять же, аналогично можно проверять (Ission, это не тебе ;)) любые события. К примеру, Heroes когда проверяет можно ли использовать какой-то skill игроку вызывает событие EntityDamageEvent (с damage равным нулю) и по результатам отменено событие или нет выполняет действия привязанные ко скиллу или же пишет сообщение о невозможности его выполнения.

Это позволяется нормально работать на нашем сервере NoobProtector'у -- я никак не привязываюсь к Heroes. Просто "умная" проверка в них сама определяет, что Васю файерболом бить нельзя, а вот Петю - можно ;)
 
В смысле? Чего не ожидал? Что я сделаю подлость и выложу процедуру на всеобщее обозрение? ;)
Я её писал когда-то давно. И тогда действительно её выстрадал: уж не помню чего я делал не так, но всё никак не мог заставить её как надо.

А выложил процедуру для того, чтобы упростить людям жизнь: многие начинают выискивать API во всяких "защитных" плагинах и проверять не защищен ли блок кем-то из них. У меня помню выпрашивали API для RoadProtector'а -- я когда глянул в то, куда он добавился, то ужаснулся. Там была поддержка Towny, LWC, Factions и ещё какой-то фигни. Ну и RoadProtector :)
А ведь все фактически меняется на вот эту (или схожую процедуру) процедуру.

Кстати, опять же, аналогично можно проверять (Ission, это не тебе ;)) любые события. К примеру, Heroes когда проверяет можно ли использовать какой-то skill игроку вызывает событие EntityDamageEvent (с damage равным нулю) и по результатам отменено событие или нет выполняет действия привязанные ко скиллу или же пишет сообщение о невозможности его выполнения.

Это позволяется нормально работать на нашем сервере NoobProtector'у -- я никак не привязываюсь к Heroes. Просто "умная" проверка в них сама определяет, что Васю файерболом бить нельзя, а вот Петю - можно ;)

Я не ожидал, что ты её будешь выспрашивать. Я думал ничего проще быть не может. Ведь тут думать почти не нужно. По поводу выкладывания темы-совета, я не против. Просто я не догадывался, что это такая страшная проблема.
 
Ission, главный момент в том, что многим такое решение просто в голову не приходит.
А на счет выспрашивать... так если не знаешь - почему бы и не спросить? У меня была какая-то проблема - проверка события проходила, а блок не ставился. Но на bukkit.org мне с ней помогли разобраться.
Если бы я не спрашивал, не читал, не пытался в чем-то разобраться, то я бы ни одного плагина бы не написал. Год назад я не знал джавы вообще (да и сейчас её не знаю - пользуюсь практически как паскалем ;)) и не знал даже с какой стороны к плагинам подступиться.
 
fromgate, я сам с Java общаюсь немного меньше полутора лет. Я тоже могу сказать, что Java не знаю. Я пользуюсь почти интуитивно. Другое дело, что я дружу с C. А вот с русским языком - не очень... My bad.
Другое дело, что у меня опыта в кодинге не мерено...
По теме: подобное решение взаимодействий с другими плагинами мне в голову пришло одним из первых. Проблем с установкой блока после этого я не испытывал. Я практически ничего и никогда не спрашиваю, а если нужно - ищу. Я знаю, что все решения по любому вопросу уже давно есть и надо просто поискать. А лучше сначало самому побиться головой - поразвивать мозги. Иногда даже бывает так, что находишь более простое и элегантное решение, нежели уже было.
 
Я практически ничего и никогда не спрашиваю, а если нужно - ищу. Я знаю, что все решения по любому вопросу уже давно есть и надо просто поискать. А лучше сначало самому побиться головой - поразвивать мозги. Иногда даже бывает так, что находишь более простое и элегантное решение, нежели уже было.
Соглашусь со всем сказанным. Хоть и не по теме моё сообщение, но просто не мог пройти мимо)
Считаю данный подход самым успешным)
 

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

Назад
Верх