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

Помогите Как определить, стоит игрок или идёт?

Bars

Старожил
Девелопер
Пользователь
Баллы
173
Java:
        Vector v = p.getVelocity();
        if ((v.getX()==0) && (v.getY()==0) && (v.getZ()==0)) // Стоит
            p.setExp(1 / 18.0F);
        else // Идёт
            p.setExp(4 / 18.0F);
Такая конструкция не работает. PlayerMoveEvent не предлагать, т.к. с его помощью нельзя узнать когда он остановился, а не по прежнему топает дальше.
 
PlayerMoveEvent не предлагать, т.к. с его помощью нельзя узнать когда он остановился, а не по прежнему топает дальше.
Тем более что эвентом нельзя отловить прыжок или убавление шума, а надо их как-то ссуммировать (то что в PME и то что в Scheduler, а они оба будут работать в разное время и полоска опыта шума будет не точной).
Java:
    private void doVisibility(Player p) {
        Vector v = p.getVelocity();
        if (p.isSneaking()) {
            p.setExp(1 / 18.0F);
        } else if (p.isSprinting()) {
            p.setExp(14 / 18.0F);
        } else {
            if ((v.getX()==0) && (v.getY()==0) && (v.getZ()==0))
                p.setExp(1 / 18.0F);
            else
                p.setExp(4 / 18.0F);
        }

        if (!((Entity) p).isOnGround()) p.setExp(p.getExp() + 4 / 18.0F);
        if ((p.getEquipment().getHelmet() != null) && (p.getEquipment().getHelmet().isSimilar(new ItemStack(397, 1, (short) 2)))) {
            p.setExp(p.getExp() - 5 / 18.0F);
        }

        attractZombies(p);
    }

Up to stars!
 
Не думаю что получится обойтись вообще без Move эвента. Иначе будет неточность, как минимум.
 
Не думаю что получится обойтись вообще без Move эвента. Иначе будет неточность, как минимум.
Шедулер с репитом раз, или даже 2 в тик обеспечит достаточную точность для чего угодно
 
Тем более что эвентом нельзя отловить прыжок
JavaScript:
package ru.hilgert.events.Events;

import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;

public class PlayerJumpEvent extends Event{
  
    private static final HandlerList handlers = new HandlerList();
  
    private Player p;
    private Location toLoc;
    private Location fromLoc;
  
    public PlayerJumpEvent(Player p, Location toLoc, Location fromLoc){
        this.toLoc = toLoc;
        this.fromLoc = fromLoc;
        this.p = p;
    }
  
    public void setCancelled(boolean status){
        if(status){
            p.teleport(this.fromLoc);
        }
    }
  
    public Player getPlayer(){
        return this.p;
    }
  
    public Location getTo(){
        return this.toLoc;
    }
  
    public Location getFrom(){
        return this.fromLoc;
    }
  
    public Location getLocation(){
        return this.p.getLocation();
    }
  
    public void setLocation(Location loc){
        p.teleport(loc);
    }
  
    public HandlerList getHandlers(){
        return handlers;
    }
  
    public static HandlerList getHandlerList(){
        return handlers;
    }
}

JavaScript:
@EventHandler
public void onMove(PlayerMoveEvent e){
     if(e.getFrom().getY() < e.getTo().getY()) {
          Bukkit.getPluginManager().callEvent(new PlayerJumpEvent(e.getPlayer(), e.getTo(), e.getFrom()));
    }
}
И не говорите что евент лишний, и вместо строки вызова евента, можно писать свой код :D
 
JavaScript:
package ru.hilgert.events.Events;

import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;

public class PlayerJumpEvent extends Event{
 
    private static final HandlerList handlers = new HandlerList();
 
    private Player p;
    private Location toLoc;
    private Location fromLoc;
 
    public PlayerJumpEvent(Player p, Location toLoc, Location fromLoc){
        this.toLoc = toLoc;
        this.fromLoc = fromLoc;
        this.p = p;
    }
 
    public void setCancelled(boolean status){
        if(status){
            p.teleport(this.fromLoc);
        }
    }
 
    public Player getPlayer(){
        return this.p;
    }
 
    public Location getTo(){
        return this.toLoc;
    }
 
    public Location getFrom(){
        return this.fromLoc;
    }
 
    public Location getLocation(){
        return this.p.getLocation();
    }
 
    public void setLocation(Location loc){
        p.teleport(loc);
    }
 
    public HandlerList getHandlers(){
        return handlers;
    }
 
    public static HandlerList getHandlerList(){
        return handlers;
    }
}

JavaScript:
@EventHandler
public void onMove(PlayerMoveEvent e){
     if(e.getFrom().getY() < e.getTo().getY()) {
          Bukkit.getPluginManager().callEvent(new PlayerJumpEvent(e.getPlayer(), e.getTo(), e.getFrom()));
    }
}
И не говорите что евент лишний, и вместо строки вызова евента, можно писать свой код :D
А тут игрок РАЗ и начал подниматься по лестнице.
 
if(e.getPlayer().getTo().getBlock() != null){
//.... :cool:
}
или
if(e.getPlayer().getTo().getBlock().getType() != Material.LADDER_BLOCK){ //Точно не помню какой там Material
//.... :cool:
}
Прыжок не решает, я написал для примера. Из кода видно, что на "видимость" влияет и эвенты, и шедуллер. В первом посте объяснил ущербность использования эвентов в моём случае. Как эвентом отоавливать осановку игрока, тобиш когда он перестаёт идти?
 
Прыжок не решает, я написал для примера. Из кода видно, что на "видимость" влияет и эвенты, и шедуллер. В первом посте объяснил ущербность использования эвентов в моём случае. Как эвентом отоавливать осановку игрока, тобиш когда он перестаёт идти?
Шедулером, в котором раз в секунду будут записываться данные о локации игрока, и его ник, если локация одна и та же == игрок стоит, если нет == ходит, логично же
 
Прыжок не решает, я написал для примера. Из кода видно, что на "видимость" влияет и эвенты, и шедуллер. В первом посте объяснил ущербность использования эвентов в моём случае. Как эвентом отоавливать осановку игрока, тобиш когда он перестаёт идти?
В майнкрафте игрок останавливается как только перестаёт слать пакеты. То бишь через тик после мув эвента игрок уже стоит на месте. Собственно поэтому Velocity игрока и не работает никогда почти. Ибо в большинстве случаев она отсылается сервером чтобы пнуть игрока и тут же забывается.
 
В майнкрафте игрок останавливается как только перестаёт слать пакеты. То бишь через тик после мув эвента игрок уже стоит на месте. Собственно поэтому Velocity игрока и не работает никогда почти. Ибо в большинстве случаев она отсылается сервером чтобы пнуть игрока и тут же забывается.
И как это сделать с технической стороны?
 
Можно посмотреть как реализована проверка на AFK в том же Essentials...
 
Можно посмотреть как реализована проверка на AFK в том же Essentials...
Ну я не настолько туп… Мне надо отловить именно остановку игрока, а не начало движения.
А ты сам подумай. Тут куча вариантов.
Самый простой - шедулер и запись тика последнего движения.
Я порылся в одном плагине… Видимо щедулер надо ставить с задержкой в один тик? И по 20 раз в секунду чекать velocity. А то у меня задержка 20 тиков (1 с), наверное поэтому и не работает.
 
Ну я не настолько туп… Мне надо отловить именно остановку игрока, а не начало движения.

Я порылся в одном плагине… Видимо щедулер надо ставить с задержкой в один тик? И по 20 раз в секунду чекать velocity. А то у меня задержка 20 тиков (1 с), наверное поэтому и не работает.
можно и 2-3-4 тика, точности будет достаточно, а ресурсов сэкономлено будет прилично.
 
Код:
private HashMap<String, Location> locs = new HashMap<String, Location>();

Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
               
                @Override
                public void run() {
                    for(Player p : Bukkit.getOnlinePlayers()){
                        Location l = p.getLocation();
                        Location ll = locs.get(p.getName());
                        if(ll == null){
                                    locs.put(p.getName(), l);
                                    continue;
                         }
                        if(l.getBlockX() == ll.getBlockX() && l.getBlockY() == ll.getBlockY() && l.getBlockZ() == ll.getBlockZ()){
                                p.sendMessage("Нельзя останавливаться.");
                         } else {
                                locs.put(p.getName(), l);
                         }
                    }
                }
            }, 0L, 8L);
 
Я использую особый отдельный листенер.
Java:
package ru.simsonic.utilities;
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<>();
    // Выдаёт Set игроков, которые "двинулись" с момента последнего опроса.
    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());
    }
}
Возможно, он не полон эвентами, но мои задачи решает на ура.
 

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

Назад
Верх