Таймер выхода из PVP

disclap

Последний из атеистов
Участник
Сообщения
54
Розыгрыши
0
Репутация
32
Реакции
6
Баллы
863
Хроники
  1. Chaotic Throne: High Five
Исходники
Присутствуют
Сборка
Own
Подскажите как прописать таймер что б статус пвп был = 0 по истечению 15 сек.
Java:
            if(getType() == ZoneType.epic)
            {
                ((Player)actor).updatePvPFlag(0);
                actor.sendMessage("You have leave the PVP Zone");
            }
При этом коде после выхода из зоны сразу убирает флаг.

Вот часть кода для startPvPFlag

Java:
    @Override
    public void startPvPFlag(Creature target)
    {
        if(_karma > 0)
            return;
        if(isOnSiegeField())
            return;
           
        long startTime = System.currentTimeMillis();
        if(target != null && target.getPvpFlag() != 0)
            startTime -= Config.PVP_TIME / 2;
        if(_pvpFlag != 0 && _lastPvpAttack > startTime)
            return;

        _lastPvpAttack = startTime;

        updatePvPFlag(1);

        if(_PvPRegTask == null)
            _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
    }

    public void stopPvPFlag()
    {
        if(_PvPRegTask != null)
        {
            _PvPRegTask.cancel(false);
            _PvPRegTask = null;
        }
        updatePvPFlag(0);
    }
 
сюда смотрите.
Каждую секунду когда чар в ПВП выполняется этот фрагмент
Спасибо за ответ, но я сделал по другому, так как изначально я вносил правки в zone.java а там ругалось на ( player. / target. ) и не знал как исправить. Так я добавил новую зону epic в compass,playable,player и все заработало только с побочными эффектами на все комбат зоны =)
Где будет правильней вносить правки? 1-й zone вариант или 2-й player ?
 
Я правильно понял что необходимо сделать чтобы при выходе из определенных зон, через N секунд скидывало флаг пвп?
Если да то решение элементарное - листенер на нужные зоны и в onLeave в них запуск таска на снятие флага, с нужной задержкой, ну или просто корректировка времени до окнчания статуса флаганого до нужного значения.
 
Я правильно понял что необходимо сделать чтобы при выходе из определенных зон, через N секунд скидывало флаг пвп?
Если да то решение элементарное - листенер на нужные зоны и в onLeave в них запуск таска на снятие флага, с нужной задержкой, ну или просто корректировка времени до окнчания статуса флаганого до нужного значения.
Я не кодер и не учил ява, но вы верно сказали, логично будет добавить в лисинер нужной зоны. Еще что подумал у меня уже есть обработка ПВП флага, можна же зделать на подобии осады, когда выходиш из зоны то получаеш флаг. Типа обработчик есть нужно только его прикрутить в нужном месте. Може быть так или всетаки в лисинер в зонелив установить флаг 2 и запускать таск время и установка флага 0 можно даже кастомное
 
Запрещено публиковать исходный код без BB-кода — CODE
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:51: error: incompatible types: int cannot be converted to boolean
[javac] if (player.getPvpFlag())
[javac] ^
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:56: error: cannot find symbol
[javac] if(_pvpFlag != 0 > startTime)
[javac] ^
[javac] symbol: variable _pvpFlag
[javac] location: class EpicZoneListener
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:59: error: cannot find symbol
[javac] if(_PvPRegTask == null)
[javac] ^
[javac] symbol: variable _PvPRegTask
[javac] location: class EpicZoneListener
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:60: error: cannot find symbol
[javac] _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
[javac] ^
[javac] symbol: variable _PvPRegTask
[javac] location: class EpicZoneListener
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:60: error: cannot find symbol
[javac] _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
[javac] ^
[javac] symbol: class PvPFlagTask
[javac] location: class EpicZoneListener
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:60: error: cannot find symbol
[javac] _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
[javac] ^
[javac] symbol: variable ThreadPoolManager
[javac] location: class EpicZoneListener
[javac] 6 errors
Что я делаю не так?

Java:
package l2s.gameserver.listener.zone.impl;

import l2s.gameserver.Config;
import l2s.gameserver.listener.zone.OnZoneEnterLeaveListener;
import l2s.gameserver.model.Creature;
import l2s.gameserver.model.Player;
import l2s.gameserver.model.Zone;
import l2s.gameserver.network.l2.components.CustomMessage;
import l2s.gameserver.utils.Location;

public class EpicZoneListener implements OnZoneEnterLeaveListener
{
    public static final OnZoneEnterLeaveListener STATIC = new EpicZoneListener();

    @Override
    public void onZoneEnter(Zone zone, Creature cha)
    {
        if(cha.isPlayable() && !cha.getPlayer().isGM())
        {
            if(cha.getLevel() > zone.getParams().getInteger("levelLimit", Integer.MAX_VALUE))
            {
                if(cha.isPlayer())
                    cha.getPlayer().sendMessage(new CustomMessage("scripts.zones.epic.banishMsg", cha.getPlayer()));
                cha.teleToLocation(Location.parseLoc(zone.getParams().getString("tele")));
            }
            else
            {
                if(!Config.ALT_USE_TRANSFORM_IN_EPIC_ZONE)
                {
                    if(cha.isPlayer())
                    {
                        Player player = cha.getPlayer();
                        if(player.getTransformation() > 0 && player.getTransformationTemplate() > 0 && !player.isCursedWeaponEquipped())
                        {
                            // TODO: Нужно ли тут какое-то сообщение?
                            player.setTransformation(0);
                            player.updatePvPFlag(1);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void onZoneLeave(Zone zone, Creature cha)
    {
                    if(cha.isPlayer())
                    {
                        Player player = cha.getPlayer();
                        if (player.getPvpFlag())
                        {
                            long startTime = System.currentTimeMillis();
                            if(player != null && player.getPvpFlag() != 0)
                            startTime -= Config.PVP_TIME / 2;
                            if(_pvpFlag != 0 > startTime)
                            return;

                            if(_PvPRegTask == null)
                            _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
                        }
                    }
    }
}
 
Последнее редактирование модератором:
disclap, добавить
Java:
private ScheduledFuture _PvPRegTask;
ниже так нельзя, ибо метод getPvpFlag возвращает не логическое значения а int
Java:
if (player.getPvpFlag())
наверно стоило так
Java:
if (player.getPvpFlag() > 0)

_pvpFlag не объявлен, и кроме как в проверке нигде не используется и не меняется его значение

тут вообще непонятно что происходит, что задумано было (будет ошибка синтаксиса как минимум)
Java:
if(_pvpFlag != 0 > startTime)
да и вообще стоит пересмотреть логику кода в методе onZoneLeave, ибо с начало дергать значения по методу из объекта player.getPvpFlag() а потом проверять объект на нуль (if(player != null && player.getPvpFlag() != 0)) как минимум не логично
 
compile-gameserver:
[delete] Deleting directory C:\Users\Downloads\L2\build\classes
[mkdir] Created dir: C:\Users\Downloads\L2\build\classes
[javac] Compiling 1978 source files to C:\Users\Downloads\L2\build\classes
[javac] C:\Users\Downloads\L2\gameserver\src\main\java\l2s\gameserver\listener\zone\impl\EpicZoneListener.java:63: error: incompatible types: EpicZoneListener cannot be converted to Player
[javac] _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
[javac] ^
[javac] Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
[javac] 1 error

Добавил я некоторые библиотеки, осталась только эта ошибка. С трудом понимаю в чем суть, я уже все библиотеки пересмотрел.

Java:
package l2s.gameserver.listener.zone.impl;

import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;

import l2s.gameserver.Config;
import l2s.gameserver.listener.zone.OnZoneEnterLeaveListener;
import l2s.gameserver.model.Creature;
import l2s.gameserver.model.Player;
import l2s.gameserver.model.Zone;
import l2s.gameserver.network.l2.components.CustomMessage;
import l2s.gameserver.utils.Location;
import l2s.gameserver.ThreadPoolManager;
import l2s.gameserver.model.GameObjectTasks.PvPFlagTask;

public class EpicZoneListener implements OnZoneEnterLeaveListener
{
    public static final OnZoneEnterLeaveListener STATIC = new EpicZoneListener();

    @Override
    public void onZoneEnter(Zone zone, Creature cha)
    {
        if(cha.isPlayable() && !cha.getPlayer().isGM())
        {
            if(cha.getLevel() > zone.getParams().getInteger("levelLimit", Integer.MAX_VALUE))
            {
                if(cha.isPlayer())
                    cha.getPlayer().sendMessage(new CustomMessage("scripts.zones.epic.banishMsg", cha.getPlayer()));
                    cha.teleToLocation(Location.parseLoc(zone.getParams().getString("tele")));
            }
            else
            {
                if(!Config.ALT_USE_TRANSFORM_IN_EPIC_ZONE)
                {
                    if(cha.isPlayer())
                    {
                        Player player = cha.getPlayer();
                        if(player.getTransformation() > 0 && player.getTransformationTemplate() > 0 && !player.isCursedWeaponEquipped())
                        {
                            // TODO: Нужно ли тут какое-то сообщение?
                            player.setTransformation(0);
                            player.updatePvPFlag(1);
                        }
                    }
                }
            }
        }
    }
    private Future<?> _PvPRegTask;
    @Override
    public void onZoneLeave(Zone zone, Creature cha)
    {
                    if(cha.isPlayer())
                    {
                        Player player = cha.getPlayer();
                        if (player.getPvpFlag() > 0)
                        {
                            long startTime = System.currentTimeMillis();
                            if(player != null && player.getPvpFlag() != 0)
                            startTime -= Config.PVP_TIME / 2;

                            if(_PvPRegTask == null)
                            _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new PvPFlagTask(this), 1000, 1000);
                        }
                    }
    }
}

По поводу
Java:
if(_pvpFlag != 0 > startTime)
Тут я просто копирнул из startPvpFlag не все убрал не был в этом уверен.

Насчет:
Java:
private ScheduledFuture _PvPRegTask;

У меня в коде встречается:
Java:
private Future<?> _PvPRegTask;
и думаю оставить так, если оно уже так написано =)
 
и думаю оставить так, если оно уже так написано =)
да можно и оставить, так как ScheduledFuture по сути расширяется классом Future
Java:
public interface ScheduledFuture<V> extends Delayed, Future<V> {
    
}
по поводу последней ошибки, при создании класса PvPFlagTask попробовать передать не this а player
Java:
_PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new GameObjectTasks.PvPFlagTask(player), 1000, 1000);
 
Так то компил работает: BUILD SUCCESSFUL
Осталось понять почему лисинер EpicZone вообще не делает то что я ему прописал.
Но если что +- рабочий вариант есть, воткну в другом месте. Где-то в Zone.java там точно работало updatePvpFlag
 
Так то компил работает: BUILD SUCCESSFUL
Осталось понять почему лисинер EpicZone вообще не делает то что я ему прописал.
Но если что +- рабочий вариант есть, воткну в другом месте. Где-то в Zone.java там точно работало updatePvpFlag
поставить логирование в методах onZoneEnter и onZoneLeave перед всеми проверками, и смотреть запускается ли слушатель (при входы в/выходе из зоны)
 
поставить логирование в методах onZoneEnter и onZoneLeave перед всеми проверками, и смотреть запускается ли слушатель (при входы в/выходе из зоны)
Я проверил работу таймера.
Вот код лисинер:
Java:
    private Future<?> _PvPRegTask;
    @Override
    public void onZoneLeave(Zone zone, Creature cha)
    {
                    if(cha.isPlayer())
                    {
                        Player player = cha.getPlayer();
                        if (player.getPvpFlag() > 0)
                        {
                            long startTime = System.currentTimeMillis();
                            startTime -= Config.PVP_TIME / 2;

                            if(_PvPRegTask == null)
                            _PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new GameObjectTasks.PvPFlagTask(player), 1000, 1000);
                        }
                    }
    }

А вот как я добавляю флаг в Zone.java
Java:
            if(getType() == ZoneType.epic)
            {
                ((Player)actor).updatePvPFlag(1);
                actor.sendMessage("You have entered the PVP Zone");
            }

И тут самое интересное что в public void onZoneLeave должен по идеи обрабатывать только когда вышел из зоны. А по факту захожу в зону получаю флаг и через 1-2 сек пропадает флаг не зависимо от того вышел из зоны или нет. Сейчас попробую в Zone.java добавить в выход из зоны а из лисенер уберу.
 
И тут самое интересное что в public void onZoneLeave должен по идеи обрабатывать только когда вышел из зоны. А по факту захожу в зону получаю флаг и через 1-2 сек пропадает флаг не зависимо от того вышел из зоны или нет.
стоит разобраться в особенностях работы методов scheduleAtFixedRate, scheduleAtFixedDelay и schedule класса ThreadPoolManager
Java:
_PvPRegTask = ThreadPoolManager.getInstance().scheduleAtFixedRate(new GameObjectTasks.PvPFlagTask(player), 1000, 1000);
в данном случае через секунду и потом каждую секунду будет запущена задача PvPFlagTask

а вот эта часть кода не понятно для чего, по сколько не используется
Java:
long startTime = System.currentTimeMillis();
startTime -= Config.PVP_TIME / 2;
 
Вот к примеру рабочий вариант, может и криво и неправильно но для меня он рабочий, только его нужно привести в нужный вид и добавить сброс таймера если pvpFlag(1)
Java:
            if(getType() == ZoneType.epic)
            {


                ((Player)actor).updatePvPFlag(2);
                new java.util.Timer().schedule(
                new java.util.TimerTask() {
                @Override
                public void run() {
                    ((Player)actor).updatePvPFlag(0);
                            }
                        },
                        20000
                );
                  actor.sendMessage("You have leave the PVP Zone");
            }

По коду выше что разобрали, (я не профи и не знаю кодинг) но как по мне код рабочий только выполняется таск не так как нужно мне из за того что нету player.getlastPvpAttack Потому что при его добавлении происходят непонятные чудеса.

Java:
    public static class PvPFlagTask extends RunnableImpl
    {
        private final HardReference<Player> _playerRef;

        public PvPFlagTask(Player player)
        {
            _playerRef = player.getRef();
        }

        @Override
        public void runImpl()
        {
            Player player = _playerRef.get();
            if(player == null)
                return;

            long diff = Math.abs(System.currentTimeMillis() - player.getlastPvpAttack());
            if(diff > Config.PVP_TIME)
                player.stopPvPFlag();
            else if(diff > Config.PVP_TIME - 20000)
                player.updatePvPFlag(2);
            else
                player.updatePvPFlag(1);
        }
    }

_PvPRegTask - при выходе начинает таймер и идет по кругу он походу выполняет вот это
Java:
    public void stopPvPFlag()
    {
        if(_PvPRegTask != null)
        {
            _PvPRegTask.cancel(false);
            _PvPRegTask = null;
        }
        updatePvPFlag(0);
    }

и снова запускается. Может я и не прав, но с виду так как будто вечно сбрасывает pvpFlag на = 0
 
и снова запускается.
стоит разобраться в особенностях работы методов scheduleAtFixedRate, scheduleAtFixedDelay и schedule класса ThreadPoolManager
в данном случае через секунду и потом каждую секунду будет запущена задача PvPFlagTask
ну не знаю как еще тебе помочь)

вот если так?
Java:
_PvPRegTask = ThreadPoolManager.getInstance().schedule(new GameObjectTasks.PvPFlagTask(player), 1000);
1000 - через сколько миллисекунд будет запущена задача PvPFlagTask после выхода из зоны

и по идеи после определения _PvPRegTask уже будет не null, и при следующем выходе из зоны новая задача не будет запущена
может как то проверять ее состояние, например так
Java:
if ( _PvPRegTask == null || _PvPRegTask.isDone() )
или как-то по другому

если самому не допрет как сделать, советую раздел Ищу исполнителя
 
ну не знаю как еще тебе помочь)

вот если так?
Java:
_PvPRegTask = ThreadPoolManager.getInstance().schedule(new GameObjectTasks.PvPFlagTask(player), 1000);
1000 - через сколько миллисекунд будет запущена задача PvPFlagTask после выхода из зоны

и по идеи после определения _PvPRegTask уже будет не null, и при следующем выходе из зоны новая задача не будет запущена
может как то проверять ее состояние, например так
Java:
if ( _PvPRegTask == null || _PvPRegTask.isDone() )
или как-то по другому

если самому не допрет как сделать, советую раздел Ищу исполнителя
И на этом огромное спасибо, я не ищу исполнителя мне просто интересно свободное время потратить впустую =) хочу немного узнать java. Сейчас почитаю scheduleAtFixedRate, scheduleAtFixedDelay и schedule класса ThreadPoolManager
 
Назад
Сверху Снизу