/* * This file is part of aion-unique <aion-unique.org>. * * aion-unique 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. * * aion-unique 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 aion-unique. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.gameserver.restrictions; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Comparator; import org.apache.commons.lang.ArrayUtils; import com.aionemu.gameserver.model.gameobjects.VisibleObject; import com.aionemu.gameserver.model.gameobjects.player.Player; import com.aionemu.gameserver.skillengine.model.Skill; /** * @author lord_rex * * This class is a Manager for restrictions. * This is a very useful system, you can use that for: * game restrictions, events restrictions, quests restrictions, * instances restrictions, customs restrictions. * * @Example: Open a new class like this: * public class AppleRestrictions extends AbstractRestrictions * { * @Override * public boolean canEatApple(Player player) * { * if(player.getController().isInEvent()) { // only example, don't forget! * return true; // player can eat apple in event. * } * return false; // player cannot eat apple in normal game. * } * } */ public final class RestrictionsManager { private RestrictionsManager() { } private static enum RestrictionMode implements Comparator<Restrictions> { isRestricted, canAttack, canAffectBySkill, canUseSkill, canChat, canInviteToGroup, canChangeEquip, canTrade, canUseWarehouse, // TODO ; private final Method METHOD; private RestrictionMode() { for(Method method : Restrictions.class.getMethods()) { if(name().equals(method.getName())) { METHOD = method; return; } } throw new InternalError(); } private boolean equalsMethod(Method method) { if(!METHOD.getName().equals(method.getName())) return false; if(!METHOD.getReturnType().equals(method.getReturnType())) return false; return Arrays.equals(METHOD.getParameterTypes(), method.getParameterTypes()); } private static final RestrictionMode[] VALUES = RestrictionMode.values(); private static RestrictionMode parse(Method method) { for(RestrictionMode mode : VALUES) { if(mode.equalsMethod(method)) return mode; } return null; } @Override public int compare(Restrictions o1, Restrictions o2) { return Double.compare(getPriority(o2), getPriority(o1)); } private double getPriority(Restrictions restriction) { RestrictionPriority a1 = getMatchingMethod(restriction.getClass()).getAnnotation(RestrictionPriority.class); if(a1 != null) return a1.value(); RestrictionPriority a2 = restriction.getClass().getAnnotation(RestrictionPriority.class); if(a2 != null) return a2.value(); return RestrictionPriority.DEFAULT_PRIORITY; } private Method getMatchingMethod(Class<? extends Restrictions> clazz) { for(Method method : clazz.getMethods()) { if(equalsMethod(method)) return method; } throw new InternalError(); } } private static final Restrictions[][] RESTRICTIONS = new Restrictions[RestrictionMode.VALUES.length][0]; public synchronized static void activate(Restrictions restriction) { for(Method method : restriction.getClass().getMethods()) { RestrictionMode mode = RestrictionMode.parse(method); if(mode == null) continue; if(method.getAnnotation(DisabledRestriction.class) != null) continue; Restrictions[] restrictions = RESTRICTIONS[mode.ordinal()]; if(!ArrayUtils.contains(restrictions, restriction)) restrictions = (Restrictions[]) ArrayUtils.add(restrictions, restriction); Arrays.sort(restrictions, mode); RESTRICTIONS[mode.ordinal()] = restrictions; } } public synchronized static void deactivate(Restrictions restriction) { for(RestrictionMode mode : RestrictionMode.VALUES) { Restrictions[] restrictions = RESTRICTIONS[mode.ordinal()]; for(int index; (index = ArrayUtils.indexOf(restrictions, restriction)) != -1;) restrictions = (Restrictions[]) ArrayUtils.remove(restrictions, index); RESTRICTIONS[mode.ordinal()] = restrictions; } } static { // This is the Restrictions when player is in normal game. activate(new PlayerRestrictions()); // This is the Restrictions when player is in shutdown. activate(new ShutdownRestrictions()); // This is the Restrictions when player is in prison. activate(new PrisonRestrictions()); } /** * This function can be used for activate one restriction. * Example: * * public static boolean startAppleEatingEvent(Player player) * { * if(RestrictionsManager.isRestricted(player, AppleEatingEventRestriction.class)) * return false; * * return true; * } */ public static boolean isRestricted(Player player, Class<? extends Restrictions> callingRestriction) { if(player == null) return true; for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.isRestricted.ordinal()]) { if(!restrictions.isRestricted(player, callingRestriction)) return false; } return false; } /** * This function created for enable/disable attack. * * @param player * @param target */ public static boolean canAttack(Player player, VisibleObject target) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canAttack.ordinal()]) { if(!restrictions.canAttack(player, target)) return false; } return true; } /** * This function is created for enable/disable on specific target. * * @param player * @param target */ public static boolean canAffectBySkill(Player player, VisibleObject target) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canAffectBySkill.ordinal()]) { if(!restrictions.canAffectBySkill(player, target)) return false; } return true; } /** * Check whether player can use such skill * * @param player * @param skill * @return */ public static boolean canUseSkill(Player player, Skill skill) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canUseSkill.ordinal()]) { if(!restrictions.canUseSkill(player, skill)) return false; } return true; } /** * This function is created for enable/disable chat. * * @param player */ public static boolean canChat(Player player) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canChat.ordinal()]) { if(!restrictions.canChat(player)) return false; } return true; } /** * This function is created for enable/disable invite to group. * * @param player * @param target */ public static boolean canInviteToGroup(Player player, Player target) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canInviteToGroup.ordinal()]) { if(!restrictions.canInviteToGroup(player, target)) return false; } return true; } /** * This function is created for enable/disable equip change. * * @param player */ public static boolean canChangeEquip(Player player) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canChangeEquip.ordinal()]) { if(!restrictions.canChangeEquip(player)) return false; } return true; } /** * Check whether player can perform trade * * @param player * @return true or false */ public static boolean canTrade(Player player) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canTrade.ordinal()]) { if(!restrictions.canTrade(player)) return false; } return true; } /** * Check whether player can use warehouse * * @param player * @return true or false */ public static boolean canUseWarehouse(Player player) { for(Restrictions restrictions : RESTRICTIONS[RestrictionMode.canUseWarehouse.ordinal()]) { if(!restrictions.canUseWarehouse(player)) return false; } return true; } }