테스트

aion-server 4.8

Gitteol
최고관리자 · 1 · 💬 0 클론/새로받기
 4.8 61f661d · 1 commits 새로받기(Pull)
game-server/src/com/aionemu/gameserver/world/MapRegion.java
package com.aionemu.gameserver.world;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.gameserver.ai.AIState;
import com.aionemu.gameserver.ai.event.AIEventType;
import com.aionemu.gameserver.configs.main.SiegeConfig;
import com.aionemu.gameserver.model.gameobjects.Creature;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.siege.SiegeNpc;
import com.aionemu.gameserver.model.templates.zone.ZoneClassName;
import com.aionemu.gameserver.utils.ThreadPoolManager;
import com.aionemu.gameserver.world.zone.ZoneInstance;
import com.aionemu.gameserver.world.zone.ZoneName;

/**
 * Just some part of map.
 * 
 * @author -Nemesiss-
 */
public class MapRegion {

	private static final Logger log = LoggerFactory.getLogger(MapRegion.class);

	/**
	 * Region ID of this map region (not world ID).
	 */
	private final int regionId;
	/**
	 * WorldMapInstance which is parent of this map region.
	 */
	private final WorldMapInstance parent;
	/**
	 * Surrounding regions + self.
	 */
	private MapRegion[] neighbours = new MapRegion[] { this };
	/**
	 * Objects in this map region.
	 */
	private final Map<Integer, VisibleObject> objects = new ConcurrentHashMap<>();

	private final AtomicInteger playerCount = new AtomicInteger(0);

	private final AtomicBoolean regionActive = new AtomicBoolean(false);

	private final int zoneCount;

	/**
	 * Zones in this region
	 */
	private Map<Integer, TreeSet<ZoneInstance>> zoneMap;

	MapRegion(int id, WorldMapInstance parent, ZoneInstance[] zones) {
		this.regionId = id;
		this.parent = parent;
		this.zoneCount = zones.length;
		createZoneMap(zones);
	}

	public int getRegionId() {
		return regionId;
	}

	public WorldMapInstance getParent() {
		return parent;
	}

	public Map<Integer, VisibleObject> getObjects() {
		return objects;
	}

	public MapRegion[] getNeighbours() {
		return neighbours;
	}

	/**
	 * Add neighbour region to this region neighbours list.
	 */
	void addNeighbourRegion(MapRegion neighbour) {
		neighbours = ArrayUtils.add(neighbours, neighbour);
	}

	/**
	 * Add AionObject to this region objects list.
	 */
	void add(VisibleObject object) {
		if (objects.put(object.getObjectId(), object) == null) {
			if (object instanceof Player)
				checkActiveness(playerCount.incrementAndGet() > 0);
		}
	}

	/**
	 * Remove AionObject from region objects list.
	 */
	void remove(VisibleObject object) {
		if (objects.remove(object.getObjectId()) != null)
			if (object instanceof Player) {
				checkActiveness(playerCount.decrementAndGet() > 0);
			}
	}

	private void checkActiveness(boolean active) {
		if (active && regionActive.compareAndSet(false, true)) {
			startActivation();
		} else if (!active && !parent.getParent().isInstanceType() && parent.getMapId() != 400030000) {
			startDeactivation();
		}
	}

	private void startActivation() {
		ThreadPoolManager.getInstance().schedule(() -> {
			log.debug("Activating in map {} region {}", getParent().getMapId(), regionId);
			MapRegion.this.activateObjects();
			for (MapRegion neighbor : getNeighbours()) {
				neighbor.activate();
			}
		}, 1000);
	}

	private void startDeactivation() {
		ThreadPoolManager.getInstance().schedule(() -> {
			log.debug("Deactivating inactive regions around region {} on map {} [{}]", regionId, getParent().getMapId(), getParent().getInstanceId());
			List<Creature> walkers = new ArrayList<>();
			for (MapRegion neighbor : getNeighbours()) {
				if (!neighbor.isNeighboursActive() && neighbor.deactivate()) {
					for (VisibleObject o : neighbor.getObjects().values()) {
						if (o instanceof Creature creature && creature.getAi().getState() == AIState.WALKING)
							walkers.add(creature);
					}
				}
			}
			walkers.removeIf(w -> w.getPosition().isMapRegionActive());
			if (walkers.size() > 2) { // small threshold to accommodate the walkers near the borders of deactivated regions
				String npcs = walkers.stream().map(VisibleObject::toString).collect(Collectors.joining("\n"));
				log.warn("There are {} objects walking on inactive map {} [{}]:\n{}", walkers.size(), getParent().getMapId(), getParent().getInstanceId(),
					npcs);
			}
		}, 60000);
	}

	public boolean activate() {
		if (regionActive.compareAndSet(false, true)) {
			activateObjects();
			return true;
		}
		return false;
	}

	/**
	 * Send ACTIVATE event to all objects with AI
	 */
	private void activateObjects() {
		for (VisibleObject visObject : objects.values()) {
			if (visObject instanceof Creature creature) {
				creature.getAi().onGeneralEvent(AIEventType.ACTIVATE);
			}
		}
	}

	public boolean deactivate() {
		if (regionActive.compareAndSet(true, false)) {
			deactivateObjects();
			return true;
		}
		return false;
	}

	/**
	 * Send DEACTIVATE event to all objects with AI
	 */
	private void deactivateObjects() {
		for (VisibleObject visObject : objects.values()) {
			if (visObject instanceof Creature creature && !(SiegeConfig.BALAUR_AUTO_ASSAULT && visObject instanceof SiegeNpc) && !creature.isFlag()
				&& !creature.isRaidMonster()) {
				creature.getAi().onGeneralEvent(AIEventType.DEACTIVATE);
			}
		}
	}

	public boolean isActive() {
		return regionActive.get();
	}

	private boolean isNeighboursActive() {
		for (MapRegion r : neighbours) {
			if (r.regionActive.get() && r.playerCount.get() > 0)
				return true;
		}
		return false;
	}

	public void revalidateZones(Creature creature) {
		for (Entry<Integer, TreeSet<ZoneInstance>> e : zoneMap.entrySet()) {
			boolean foundZone = false;
			int category = e.getKey();
			TreeSet<ZoneInstance> zones = e.getValue();
			for (ZoneInstance zone : zones) {
				if (!creature.isSpawned() || (category != -1 && foundZone)) {
					zone.onLeave(creature);
					continue;
				}
				if (!zone.revalidate(creature)) {
					zone.onLeave(creature);
					continue;
				}
				if (category != -1) {
					foundZone = true;
				}
				zone.onEnter(creature);
			}
		}
	}

	public List<ZoneInstance> findZones(Creature creature) {
		List<ZoneInstance> z = new ArrayList<>();
		for (Entry<Integer, TreeSet<ZoneInstance>> e : zoneMap.entrySet()) {
			TreeSet<ZoneInstance> zones = e.getValue();
			for (ZoneInstance zone : zones) {
				if (zone.isInsideCreature(creature)) {
					z.add(zone);
				}
			}
		}
		return z;
	}

	public boolean onDie(Creature attacker, Creature target) {
		for (Entry<Integer, TreeSet<ZoneInstance>> e : zoneMap.entrySet()) {
			TreeSet<ZoneInstance> zones = e.getValue();
			for (ZoneInstance zone : zones) {
				if (zone.isInsideCreature(target)) {
					if (zone.onDie(attacker, target))
						return true;
				}
			}
		}
		return false;
	}

	public boolean isInsideZone(ZoneName zoneName, float x, float y, float z) {
		for (Entry<Integer, TreeSet<ZoneInstance>> e : zoneMap.entrySet()) {
			TreeSet<ZoneInstance> zones = e.getValue();
			for (ZoneInstance zone : zones) {
				if (zone.getZoneTemplate().getName() != zoneName)
					continue;
				return zone.isInsideCordinate(x, y, z);
			}
		}
		return false;
	}

	public boolean isInsideZone(ZoneName zoneName, Creature creature) {
		for (Entry<Integer, TreeSet<ZoneInstance>> e : zoneMap.entrySet()) {
			TreeSet<ZoneInstance> zones = e.getValue();
			for (ZoneInstance zone : zones) {
				if (zone.getZoneTemplate().getName() == zoneName)
					return zone.isInsideCreature(creature);
			}
		}
		return false;
	}

	/**
	 * Item use zones always have the same names instances, while we have unique names; Thus, a special check for item use.
	 */
	public boolean isInsideItemUseZone(ZoneName zoneName, Creature creature) {
		boolean checkFortresses = "_ABYSS_CASTLE_AREA_".equals(zoneName.name()); // some items have this special zonename in uselimits
		for (Entry<Integer, TreeSet<ZoneInstance>> e : zoneMap.entrySet()) {
			TreeSet<ZoneInstance> zones = e.getValue();
			for (ZoneInstance zone : zones) {
				if (checkFortresses) {
					if (!zone.getZoneTemplate().getZoneType().equals(ZoneClassName.FORT))
						continue;
				} else {
					if (!zone.getZoneTemplate().getXmlName().startsWith(zoneName.toString()))
						continue;
				}
				if (zone.isInsideCreature(creature))
					return true;
			}
		}
		return false;
	}

	private void createZoneMap(ZoneInstance[] zones) {
		zoneMap = new LinkedHashMap<>();
		for (ZoneInstance zone : zones) {
			int category = -1;
			if (zone.getZoneTemplate().getPriority() != 0) {
				category = zone.getZoneTemplate().getZoneType().ordinal();
			}
			zoneMap.computeIfAbsent(category, k -> new TreeSet<>()).add(zone);
		}
	}

	public int getZoneCount() {
		return zoneCount;
	}
}

📎 첨부파일

댓글 작성 권한이 없습니다.
🏆 포인트 랭킹 TOP 10
순위 닉네임 포인트
1 no_profile 타키야겐지쪽지보내기 자기소개 아이디로 검색 전체게시물 102,949
2 no_profile 동가리쪽지보내기 자기소개 아이디로 검색 전체게시물 63,733
3 no_profile 라프텔쪽지보내기 자기소개 아이디로 검색 전체게시물 51,771
4 no_profile 불멸의행복쪽지보내기 자기소개 아이디로 검색 전체게시물 36,923
5 서번트쪽지보내기 자기소개 아이디로 검색 전체게시물 35,011
6 no_profile 닥터스쪽지보내기 자기소개 아이디로 검색 전체게시물 29,470
7 no_profile 검은고양이쪽지보내기 자기소개 아이디로 검색 전체게시물 29,077
8 no_profile Revolution쪽지보내기 자기소개 아이디로 검색 전체게시물 28,199
9 no_profile 보거스쪽지보내기 자기소개 아이디로 검색 전체게시물 26,731
10 no_profile 호롤롤로쪽지보내기 자기소개 아이디로 검색 전체게시물 17,020
알림 0