Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Работа со скриптами (https://forum.zone-game.info/forumdisplay.php?f=37)
-   -   Задержка после выполнения команды. (https://forum.zone-game.info/showthread.php?t=29731)

L2J 25.06.2013 13:58

Задержка после выполнения команды.
 
Имеется скрипт бафера, как сделать задержку, дабы не флудили бафами и хилами, сервет ляжет :D :redlol:
Вот код:
/*
 * Copyright (C) 2004-2013 L2J DataPack
 * 
 * This file is part of L2J DataPack.
 * 
 * L2J DataPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * L2J DataPack is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package handlers.bypasshandlers;
 
import java.util.StringTokenizer;
import java.util.logging.Level;
 
import com.l2jserver.gameserver.handler.IBypassHandler;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.zone.ZoneId;
 
/**
 * @author Xaras2
 */
public class ArenaBuff implements IBypassHandler
{
	private static final String[] COMMANDS =
	{
		"ArenaBuffs",
		"HPRecovery",
		"CPRecovery"
	};
 
	private final int[][] BUFFS =
	{
		{ // Fighter Buffs
			6803,
			6804,
			6808,
			6809,
			6811,
			6812,
			6805,
			6806,
			6807
		},
		{ // Mage Buffs
			6803,
			6804,
			6808,
			6809,
			6811,
			6812,
			6805,
			6806,
			6807
		}
	};
 
	@Override
	public boolean useBypass(String command, L2PcInstance activeChar, L2Character target)
	{
		if (!target.isNpc())
		{
			return false;
		}
 
		final L2Npc npc = (L2Npc) target;
		final StringTokenizer st = new StringTokenizer(command);
		try
		{
			String cmd = st.nextToken();
 
			if (cmd.equalsIgnoreCase(COMMANDS[0]))
			{
 
				for (int skillId : BUFFS[activeChar.isMageClass() ? 1 : 0])
				{
					SkillHolder skill = new SkillHolder(skillId, 1);
 
					if (skill.getSkill() != null)
					{
						npc.setTarget(activeChar);
						npc.doCast(skill.getSkill());
					}
				}
				return true;
			}
			else if (cmd.equalsIgnoreCase(COMMANDS[1])) //Heal
			{
				if (activeChar.isInsideZone(ZoneId.PVP)) // Cannot be used while inside the pvp zone
				{
					return false;
				}
 
				SkillHolder skill = new SkillHolder(6817, 1);
				if (skill.getSkill() != null)
				{
					npc.setTarget(activeChar);
					npc.doCast(skill.getSkill());
				}
				return true;
 
			}
		}
		catch (Exception e)
		{
			_log.log(Level.WARNING, "Exception in " + getClass().getSimpleName(), e);
		}
		return false;
	}
 
	@Override
	public String[] getBypassList()
	{
		return COMMANDS;
	}
}
 
Code: Java

Shayne 25.06.2013 15:16

Re: Задержка после выполнения команды.
 
Код:

Thread.sleep(ms)
Если вы не в состоянии набрать 2 слова в гугле, стоит задуматься...
Или снова ждете пока сделают за вас?

Ashe 25.06.2013 15:47

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от Shayne (Сообщение 307500)
Код:

Thread.sleep(ms)

Таким способом Вы "повесите" весь сервер.

Можно воспользоваться обыкновенным таймером, то есть считывать системное время в переменную при бафе и прибавлять к ней некоторый промежуток времени на который вы хотите запретить повторное использование и проверять перед повторным использованием.

Или же можно воспользоваться ThredPoolManager.

Smiler 25.06.2013 15:57

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от Ashe (Сообщение 307502)
Таким способом Вы "повесите" весь сервер.

Можно воспользоваться обыкновенным таймером, то есть считывать системное время в переменную при бафе и прибавлять к ней некоторый промежуток времени на который вы хотите запретить повторное использование и проверять перед повторным использованием.

Или же можно воспользоваться ThredPoolManager.

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

Ashe 25.06.2013 16:03

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от MHard (Сообщение 307504)
ну не весь сервер а поток игрока заснет.
и тут простым таймером не обойтись, я так понимаю таймер каждому игроку надо делать и в БД сохранять желательно, а то так не дождешся очереди на свой баф.

В БД это слишком накладно на ресурсы. Может просто создать карту(игрок, кулдаун) и проверять по ней.

Shayne 25.06.2013 16:07

Re: Задержка после выполнения команды.
 
А если баф в отдельный поток и его стопать? Или слишком затратно?

Smiler 25.06.2013 16:09

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от Ashe (Сообщение 307505)
В БД это слишком накладно на ресурсы. Может просто создать карту(игрок, кулдаун) и проверять по ней.

да вполне, но тут 3 комманды

"ArenaBuffs",
"HPRecovery",
"CPRecovery"

на каждую свой массив.

+ при рестарте сервера откаты пропадают, а если задумка автора делать КД раз в сутки?

L2J 25.06.2013 16:17

Re: Задержка после выполнения команды.
 
Команды две, аренабафс и хпрекавер, цпрекавер удалить забыл:)
Ну мне просто нужно сделать задержку хотя бы 30сек.

Ashe 25.06.2013 16:20

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от MHard (Сообщение 307507)
да вполне, но тут 3 комманды

"ArenaBuffs",
"HPRecovery",
"CPRecovery"

на каждую свой массив.

А если так Map<L2PcInstance, Map<String, Long>> ?

Цитата:

Сообщение от MHard (Сообщение 307507)
+ при рестарте сервера откаты пропадают, а если задумка автора делать КД раз в сутки?

Тогда в БД и не парить себе голову.

Zeratyl 25.06.2013 18:59

Re: Задержка после выполнения команды.
 
Если рассуждать с точки зрения нагрузки, джентльмены, то выгоднее всего выдавать баффы бессрочно сразу при заходе чара, в пакете EnterWorld, а после смерти не обнулять их.

KID 25.06.2013 19:53

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от MHard (Сообщение 307504)
ну не весь сервер а поток игрока заснет..

ооо, теперь сборки клепают по принципу 1 поток равно игрок?

Ashe 25.06.2013 20:02

Re: Задержка после выполнения команды.
 
 
/*
 * Copyright (C) 2004-2013 L2J DataPack
 * 
 * This file is part of L2J DataPack.
 * 
 * L2J DataPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * L2J DataPack is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package handlers.bypasshandlers;
 
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
 
import com.l2jserver.gameserver.handler.IBypassHandler;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.zone.ZoneId;
 
/**
 * @author Xaras2
 */
public class ArenaBuff implements IBypassHandler
{
	private static ConcurrentMap<Integer, Map<String, Long>> _map = new ConcurrentHashMap<>();
	private static final String[] COMMANDS =
	{
		"ArenaBuffs",
		"HPRecovery"
	};
 
	private final int[][] BUFFS =
	{
		{ // Fighter Buffs
			6803,
			6804,
			6808,
			6809,
			6811,
			6812,
			6805,
			6806,
			6807
		},
		{ // Mage Buffs
			6803,
			6804,
			6808,
			6809,
			6811,
			6812,
			6805,
			6806,
			6807
		}
	};
 
	@Override
	public boolean useBypass(String command, L2PcInstance activeChar, L2Character target)
	{
		if (!target.isNpc())
		{
			return false;
		}
 
		final L2Npc npc = (L2Npc) target;
		final StringTokenizer st = new StringTokenizer(command);
		try
		{
			String cmd = st.nextToken();
 
			_map.putIfAbsent(activeChar.getObjectId(), new HashMap<String, Long>());
 
			if (cmd.equalsIgnoreCase(COMMANDS[0]))
			{
				if (_map.get(activeChar.getObjectId()).get(cmd) != null)
				{
					if (_map.get(activeChar.getObjectId()).get(cmd) > System.currentTimeMillis())
					{
						activeChar.sendMessage("Покури пока, браток.");
						return false;
					}
					_map.get(activeChar.getObjectId()).clear();
				}
 
				for (int skillId : BUFFS[activeChar.isMageClass() ? 1 : 0])
				{
					SkillHolder skill = new SkillHolder(skillId, 1);
 
					if (skill.getSkill() != null)
					{
						npc.setTarget(activeChar);
						npc.doCast(skill.getSkill());
						_map.get(activeChar.getObjectId()).put(cmd, System.currentTimeMillis() + 15000); // текущее время + 15 сек задержка
					}
				}
				return true;
			}
			else if (cmd.equalsIgnoreCase(COMMANDS[1])) // Heal
			{
				if (_map.get(activeChar.getObjectId()).get(cmd) != null)
				{
					if (_map.get(activeChar.getObjectId()).get(cmd) > System.currentTimeMillis())
					{
						activeChar.sendMessage("Покури пока, браток.");
						return false;
					}
					_map.get(activeChar.getObjectId()).clear();
				}
 
				if (activeChar.isInsideZone(ZoneId.PVP)) // Cannot be used while inside the pvp zone
				{
					return false;
				}
 
				SkillHolder skill = new SkillHolder(6817, 1);
				if (skill.getSkill() != null)
				{
					npc.setTarget(activeChar);
					npc.doCast(skill.getSkill());
					_map.get(activeChar.getObjectId()).put(cmd, System.currentTimeMillis() + 15000); // текущее время + 15 сек задержка
				}
				return true;
 
			}
		}
		catch (Exception e)
		{
			_log.log(Level.WARNING, "Exception in " + getClass().getSimpleName(), e);
		}
		return false;
	}
 
	@Override
	public String[] getBypassList()
	{
		return COMMANDS;
	}
}
Code: Java

KID 25.06.2013 20:08

Re: Задержка после выполнения команды.
 
Ashe, в самом начале же все перетираешь, жесть/
Потроллил бы уже с putIfAbsent

Ashe 25.06.2013 20:13

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от KID (Сообщение 307552)
Ashe, в самом начале же все перетираешь, жесть/
Потроллил бы уже с putIfAbsent

Ты про это ?
_map.putIfAbsent(activeChar.getObjectId(), new HashMap<String, Long>());
Code: Java

linliss 25.06.2013 20:14

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от MHard (Сообщение 307504)
ну не весь сервер а поток игрока заснет.
и тут простым таймером не обойтись, я так понимаю таймер каждому игроку надо делать и в БД сохранять желательно, а то так не дождешся очереди на свой баф.

заснет не поток игрока, а один из потоков пула, который обрабатывает входящие пакеты

Добавлено через 1 минуту
с чего вообще тс взял что из-за частого бафа что-то ляжет?

Smiler 25.06.2013 20:33

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от KID (Сообщение 307548)
ооо, теперь сборки клепают по принципу 1 поток равно игрок?

Цитата:

Сообщение от linliss (Сообщение 307555)
заснет не поток игрока, а один из потоков пула, который обрабатывает входящие пакеты

суть от того что подвиснет один из потоков этих пулов

Код:

                _ioPacketsThreadPool = new ThreadPoolExecutor(Config.IO_PACKET_THREAD_CORE_SIZE, Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("I/O Packet Pool", Thread.NORM_PRIORITY + 1));
                _generalPacketsThreadPool = new ThreadPoolExecutor(Config.GENERAL_PACKET_THREAD_CORE_SIZE, Config.GENERAL_PACKET_THREAD_CORE_SIZE + 2, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Normal Packet Pool", Thread.NORM_PRIORITY + 1));

, не меняется
весь сервер не повиснет от заслипливания скрипта,но если вы так уж дословно придираетесь то пусть будет так "зависнет один из потоков обрабатывающий пакеты игрока".

Ro_0TT 25.06.2013 21:53

Re: Задержка после выполнения команды.
 
Если я правильно понял суть проблемы, то в баффер создаем мапу:
 
private Map<Integer, Long> lastUse = new ConcurrentHashMap<>;
 
Code: Java
в методе "баффа" добавляем проверку:

 
// Проверяем когда последний раз юзали метод, если давно -> добавляем время последнего использования.
int charID = player.getObjectId();
long currentTime = System.currentTimeMillis();
 
if (!lastUse.containsKey(charID ) || lastUse.get(charID) + 100 < currentTime)
	lastUse.put(charID, currentTime);
else // иначе запрещаем использование метода.
	return;
 
Code: Java

Ashe 25.06.2013 22:02

Re: Задержка после выполнения команды.
 
Ro_0TT, не совсем правильно. В бафере есть 2 команды, которые также должны учитываться, либо создавать две карты, либо мой вариант.

L2scripts-Guard 25.06.2013 23:02

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от Ashe (Сообщение 307502)
Таким способом Вы "повесите" весь сервер.

Можно воспользоваться обыкновенным таймером, то есть считывать системное время в переменную при бафе и прибавлять к ней некоторый промежуток времени на который вы хотите запретить повторное использование и проверять перед повторным использованием.

Или же можно воспользоваться ThredPoolManager.

Использовал данный момент когда писал клиенту с 1500 онлайн баффера (по его запросу) ничего кроме этого потока не висло.

Ro_0TT 25.06.2013 23:25

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от Ashe (Сообщение 307575)
Ro_0TT, не совсем правильно. В бафере есть 2 команды, которые также должны учитываться, либо создавать две карты, либо мой вариант.

По аналогии создать новый объект, в котором будет 2 переменных времени для двух команд. Еще красивее получается.. в этом же объекте проверять время и обновлять его по нужде, а при использование только запрещать использование команд.

Цитата:

Сообщение от Ashe (Сообщение 307550)
 
/*
 * Copyright (C) 2004-2013 L2J DataPack
 * 
 * This file is part of L2J DataPack.
 * 
 * L2J DataPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * L2J DataPack is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package handlers.bypasshandlers;
 
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
 
import com.l2jserver.gameserver.handler.IBypassHandler;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.zone.ZoneId;
 
/**
 * @author Xaras2
 */
public class ArenaBuff implements IBypassHandler
{
	private static ConcurrentMap<Integer, Map<String, Long>> _map = new ConcurrentHashMap<>();
	private static final String[] COMMANDS =
	{
		"ArenaBuffs",
		"HPRecovery"
	};
 
	private final int[][] BUFFS =
	{
		{ // Fighter Buffs
			6803,
			6804,
			6808,
			6809,
			6811,
			6812,
			6805,
			6806,
			6807
		},
		{ // Mage Buffs
			6803,
			6804,
			6808,
			6809,
			6811,
			6812,
			6805,
			6806,
			6807
		}
	};
 
	@Override
	public boolean useBypass(String command, L2PcInstance activeChar, L2Character target)
	{
		if (!target.isNpc())
		{
			return false;
		}
 
		final L2Npc npc = (L2Npc) target;
		final StringTokenizer st = new StringTokenizer(command);
		try
		{
			String cmd = st.nextToken();
 
			_map.putIfAbsent(activeChar.getObjectId(), new HashMap<String, Long>());
 
			if (cmd.equalsIgnoreCase(COMMANDS[0]))
			{
				if (_map.get(activeChar.getObjectId()).get(cmd) != null)
				{
					if (_map.get(activeChar.getObjectId()).get(cmd) > System.currentTimeMillis())
					{
						activeChar.sendMessage("Покури пока, браток.");
						return false;
					}
					_map.get(activeChar.getObjectId()).clear();
				}
 
				for (int skillId : BUFFS[activeChar.isMageClass() ? 1 : 0])
				{
					SkillHolder skill = new SkillHolder(skillId, 1);
 
					if (skill.getSkill() != null)
					{
						npc.setTarget(activeChar);
						npc.doCast(skill.getSkill());
						_map.get(activeChar.getObjectId()).put(cmd, System.currentTimeMillis() + 15000); // текущее время + 15 сек задержка
					}
				}
				return true;
			}
			else if (cmd.equalsIgnoreCase(COMMANDS[1])) // Heal
			{
				if (_map.get(activeChar.getObjectId()).get(cmd) != null)
				{
					if (_map.get(activeChar.getObjectId()).get(cmd) > System.currentTimeMillis())
					{
						activeChar.sendMessage("Покури пока, браток.");
						return false;
					}
					_map.get(activeChar.getObjectId()).clear();
				}
 
				if (activeChar.isInsideZone(ZoneId.PVP)) // Cannot be used while inside the pvp zone
				{
					return false;
				}
 
				SkillHolder skill = new SkillHolder(6817, 1);
				if (skill.getSkill() != null)
				{
					npc.setTarget(activeChar);
					npc.doCast(skill.getSkill());
					_map.get(activeChar.getObjectId()).put(cmd, System.currentTimeMillis() + 15000); // текущее время + 15 сек задержка
				}
				return true;
 
			}
		}
		catch (Exception e)
		{
			_log.log(Level.WARNING, "Exception in " + getClass().getSimpleName(), e);
		}
		return false;
	}
 
	@Override
	public String[] getBypassList()
	{
		return COMMANDS;
	}
}
Code: Java

Тролинг?) Вы здесь принудительно добавляете данные (заменяя старые), дальнейшие проверки с нею бессмысленны.

KID это уже подметил.

linliss 25.06.2013 23:47

Re: Задержка после выполнения команды.
 
тема вообще бесполезная... автор придумал проблему из ничего...

KID 25.06.2013 23:48

Re: Задержка после выполнения команды.
 
Цитата:

Сообщение от MHard (Сообщение 307559)
суть от того что подвиснет один из потоков этих пулов

Код:

                _ioPacketsThreadPool = new ThreadPoolExecutor(Config.IO_PACKET_THREAD_CORE_SIZE, Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("I/O Packet Pool", Thread.NORM_PRIORITY + 1));
                _generalPacketsThreadPool = new ThreadPoolExecutor(Config.GENERAL_PACKET_THREAD_CORE_SIZE, Config.GENERAL_PACKET_THREAD_CORE_SIZE + 2, 15L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new PriorityThreadFactory("Normal Packet Pool", Thread.NORM_PRIORITY + 1));

, не меняется
весь сервер не повиснет от заслипливания скрипта,но если вы так уж дословно придираетесь то пусть будет так "зависнет один из потоков обрабатывающий пакеты игрока".

Этих пулов, обрабатывающих пакетов "мало", по отношению к игрокам, 4 пула могут спокойно работать с 400 игроками

Добавлено через 4 минуты
В любом случае весь этот кусок бафера - просто ужасно написан, пишите по новой, использовать этот код крайне опасно для общего аромата вашего сервера.
Использовать concurrent карту для этого дела несколько толсто


Текущее время: 05:44. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot