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

Наверное имелся в виду WG?

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

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

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

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

Да и самому не так уж и сложно проверять. Кстати, сверху @fromgate привёл отличный пример реализации.
Спасибо. Вот только один вопрос: Не будет постоянное прослушивание PlayerMoveEvent давать большую нагрузку при больших онлайнах?
 
Shockwave, Вам же в PlayerMoveEvent не нужно выполнять что-то безумно большое. Вы просто проверяете принадлежность одной/двух координат регионам. Не думаю, что у Вас количество игроков и регионов будет таким, чтобы Вы испытали проблемы по этому поводу.

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

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

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

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

Класс листенера, который отлавливает подвигавшихся игроков:
Java:
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());
    }
}

Где-то отдельно кусок тела параллельного потока:
Java:
for(; !Thread.interrupted(); Thread.sleep(granularity))
   for(Player player : movedPlayers.getMovedPlayersAsync())
      if(regionListProvider.IsRegionListChanged(player))
         { /* Сделать что-то ваше */ }
Гранулярность позволяет задать периодичность обработки, для моих задач стоит 1 секунда, что вполне решает поставленные задачи.
Ну и то, как я делаю поиск регионов:
Java:
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% рабочий код :)
 
Назад
Верх