1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Помогите Отслеживание ивентов WG

Тема в разделе "Разработка плагинов для новичков", создана пользователем Shockwave, 2 июн 2014.

  1. Автор темы
    Shockwave

    Shockwave Старожил Пользователь

    Баллы:
    103
    Нужно ловить например ивент WG входа в регион и выполнять некий код. Прошу помочь(лучше всего кодом)
     
    Последнее редактирование: 3 июн 2014
    Лайка3, Лайка2, mahimamax и ещё 1-му нравится это.
  2. fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Наверное имелся в виду WG?

    В WG события связанные со входом/выходом в регион отсутствуют. Поэтому по сути их нужно самому реализовывать (ну или, если не создавать сами события, то по крайней мере проверять вошёл игрок в новый регион или нет).

    Собственно вот пример из ReActions, метод определяющий по двум координатам (он у меня вызывается из PlayerMoveEvent) входит ли игрок в новый регион и если да - то вызывает событие (это событие "собственного" производства - вместо вызова события можно выполнять свой код).
     
    Лайка3, Лайка2, mahimamax и 2 другим нравится это.
  3. Gentalion

    Gentalion Активный участник Пользователь

    Баллы:
    93
    Имя в Minecraft:
    Gentalion
    Есть плагин WG Events, загугли сам.

    Да и самому не так уж и сложно проверять. Кстати, сверху @fromgate привёл отличный пример реализации.
     
  4. Автор темы
    Shockwave

    Shockwave Старожил Пользователь

    Баллы:
    103
    Спасибо. Вот только один вопрос: Не будет постоянное прослушивание PlayerMoveEvent давать большую нагрузку при больших онлайнах?
     
    Лайка3, Лайка2 и mahimamax нравится это.
  5. fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Shockwave, Вам же в PlayerMoveEvent не нужно выполнять что-то безумно большое. Вы просто проверяете принадлежность одной/двух координат регионам. Не думаю, что у Вас количество игроков и регионов будет таким, чтобы Вы испытали проблемы по этому поводу.

    Начинайте беспокоиться, когда Вы начнёте выполнять в PlayerMoveEvent что-то конкретное (ну предположим, менять алмазы на уголь на расстоянии 500 блоков вокруг игрока ;))
    Если задача трудоемкая, то тогда выносите её в отдельную задачу (несинхронизированную) и запускайте из из обработчика события.

    Ну и если есть сомнения, не поленитесь, сделайте собственный профайлер. Это самый надежный способ их снять. Я для себя вопрос закрыл — в ReActions есть механизма подсчитывающий сколько и чего ReActions выполняет с разбивкой по тикам — т.е. можно оценить сколько процентов от тика приходится на выполнение методов ReActions (эта процедура, правда в сам плагин не встроена, — подключается и компилируется по мере необходимости). Когда были подозрения, что какие-то действия выполняются слишком долго, то снималась информация с живого сервера, активно использующего ReActions (в т.ч. активаторы связанные с регионами) — и мы даже близко не подошли к тому, чтобы у меня возникла необходимость что-то менять. В процессе, помню что-то оптимизировал, но это был необязательно, по большому счету.
     
  6. Автор темы
    Shockwave

    Shockwave Старожил Пользователь

    Баллы:
    103
    Спасибо за полный и ясный ответ. Буду знать теперь)
     
  7. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Поделюсь своим опытом:

    Класс листенера, который отлавливает подвигавшихся игроков:
    Код:
    import java.util.HashSet;
    import org.bukkit.entity.Player;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerChangedWorldEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerMoveEvent;
    import org.bukkit.event.player.PlayerTeleportEvent;
    
    public class MovingPlayersCatcher implements Listener
    {
        private final HashSet<Player> movedPlayers = new HashSet<>();
        public synchronized HashSet<Player> getMovedPlayersAsync()
        {
            HashSet<Player> result = new HashSet<>(movedPlayers);
            movedPlayers.clear();
            return result;
        }
        @org.bukkit.event.EventHandler
        protected synchronized void onPlayerJoin(PlayerJoinEvent event)
        {
            movedPlayers.add(event.getPlayer());
        }
        @org.bukkit.event.EventHandler
        protected synchronized void onPlayerMove(PlayerMoveEvent event)
        {
            movedPlayers.add(event.getPlayer());
        }
        @org.bukkit.event.EventHandler
        protected synchronized void onPlayerTeleport(PlayerTeleportEvent event)
        {
            movedPlayers.add(event.getPlayer());
        }
        @org.bukkit.event.EventHandler
        protected synchronized void onPlayerChangedWorld(PlayerChangedWorldEvent event)
        {
            movedPlayers.add(event.getPlayer());
        }
    }
    Где-то отдельно кусок тела параллельного потока:
    Код:
    for(; !Thread.interrupted(); Thread.sleep(granularity))
       for(Player player : movedPlayers.getMovedPlayersAsync())
          if(regionListProvider.IsRegionListChanged(player))
             { /* Сделать что-то ваше */ }
    Гранулярность позволяет задать периодичность обработки, для моих задач стоит 1 секунда, что вполне решает поставленные задачи.
    Ну и то, как я делаю поиск регионов:
    Код:
    import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
    import com.sk89q.worldguard.protection.ApplicableRegionSet;
    import com.sk89q.worldguard.protection.managers.RegionManager;
    import com.sk89q.worldguard.protection.regions.ProtectedRegion;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import org.bukkit.Location;
    import org.bukkit.World;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.Plugin;
    
    public final class RegionListProviders
    {
        private final MainPluginClass plugin;
        private Plugin worldguard;
        private final Map<Player, Set<String>> regionsByPlayer = new HashMap<>();
        private final Map<Player, Integer> playerRegionHashes = new HashMap<>();
        private final Map<Player, World> playerLastWorld = new HashMap<>();
        public RegionListProviders(MainPluginClass rscp)
        {
            this.plugin = rscp;
        }
        public synchronized void integrate()
        {
            // WorldGuard
            if(plugin.settings.isUseWorldGuard())
            {
                final Plugin pluginWG = plugin.getServer().getPluginManager().getPlugin("WorldGuard");
                if((pluginWG != null) && (pluginWG instanceof WorldGuardPlugin))
                {
                    this.worldguard = pluginWG;
                    MainPluginClass.consoleLog.info("[rscp] WorldGuard was found and integrated.");
                } else {
                    this.worldguard = null;
                    MainPluginClass.consoleLog.info("[rscp] WorldGuard was not found.");
                }
            } else
                this.worldguard = null;
        }
        public synchronized void deintegrate()
        {
            this.worldguard = null;
            this.residence = null;
        }
        public synchronized boolean IsRegionListChanged(Player player)
        {
            final Location location = player.getLocation();
            final World world = location.getWorld();
            final Set<String> playerRegions = new HashSet<>();
            // WorldGuard
            if(worldguard != null && worldguard.isEnabled())
                try
                {
                    final WorldGuardPlugin pluginWG = (WorldGuardPlugin)worldguard;
                    final RegionManager rman = pluginWG.getRegionManager(world);
                    if(rman == null)
                        return false;
                    // Get list
                    final ApplicableRegionSet appregs = rman.getApplicableRegions(location);
                    for(ProtectedRegion region : appregs)
                        playerRegions.add(region.getId());
                } catch(RuntimeException ex) {
                }
            // Is it changed?
            int hashcode = playerRegions.hashCode();
            if(playerLastWorld.containsKey(player))
                if(playerLastWorld.get(player).equals(world))
                    if(hashcode == playerRegionHashes.get(player))
                        return false;
            // Update
            playerRegionHashes.put(player, hashcode);
            regionsByPlayer.put(player, playerRegions);
            playerLastWorld.put(player, world);
            return true;
        }
        public synchronized Set<String> GetRegionList(Player player)
        {
            Set<String> result = regionsByPlayer.get(player);
            return (result != null) ? result : Collections.<String>emptySet();
        }
        public synchronized void removePlayer(Player player)
        {
            playerRegionHashes.remove(player);
            regionsByPlayer.remove(player);
            playerLastWorld.remove(player);
        }
    }
    Тут на самом деле задача другая немного, просто выяснить, изменился и список регионов, в которых находится игрок, или нет. Но при желании вы сможете это довести до нужного вам состояния. Я кое что лишнее подрезал, так что не обещаю, что это 100% рабочий код :)
     
    Лайка3, Лайка2, fromgate и 2 другим нравится это.

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