테스트

aion-server 4.8

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

import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.gameserver.configs.main.AutoGroupConfig;
import com.aionemu.gameserver.configs.main.InstanceConfig;
import com.aionemu.gameserver.configs.main.MembershipConfig;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.instance.InstanceEngine;
import com.aionemu.gameserver.instance.handlers.InstanceHandler;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.house.House;
import com.aionemu.gameserver.model.team.GeneralTeam;
import com.aionemu.gameserver.model.templates.housing.BuildingType;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.services.AutoGroupService;
import com.aionemu.gameserver.services.event.Event;
import com.aionemu.gameserver.services.event.EventService;
import com.aionemu.gameserver.services.teleport.TeleportService;
import com.aionemu.gameserver.spawnengine.SpawnEngine;
import com.aionemu.gameserver.spawnengine.TemporarySpawnEngine;
import com.aionemu.gameserver.spawnengine.WalkerFormator;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.ThreadPoolManager;
import com.aionemu.gameserver.world.*;
import com.aionemu.gameserver.world.zone.ZoneInstance;

/**
 * @author ATracer
 */
public class InstanceService {

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

	public static WorldMapInstance getNextAvailableInstance(int worldId, int ownerId, byte difficultyId, Function<WorldMapInstance, InstanceHandler> instanceHandlerSupplier, int maxPlayers, boolean autoDestroy) {
		WorldMap map = World.getInstance().getWorldMap(worldId);

		if (!map.isInstanceType() || map.getWorldType() == WorldType.PANESTERRA && !map.getAvailableInstanceIds().isEmpty())
			throw new UnsupportedOperationException("Invalid call for next available instance  of " + worldId);

		WorldMapInstance instance;
		if (instanceHandlerSupplier == null) {
			instance = WorldMapInstanceFactory.createWorldMapInstance(map, ownerId, InstanceEngine.getInstance()::getNewInstanceHandler, maxPlayers);
			SpawnEngine.spawnInstance(instance, difficultyId, ownerId);
		}	else {
			instance = WorldMapInstanceFactory.createWorldMapInstance(map, ownerId, instanceHandlerSupplier, maxPlayers);
			EventService.getInstance().getActiveEvents().stream().map(Event::getEventTemplate).filter(t -> t.getSpawns() != null).forEach(
				t -> SpawnEngine.spawnEventSpawns(instance, difficultyId, ownerId, t));
		}
		instance.getInstanceHandler().onInstanceCreate();

		// finally start the checker
		if (autoDestroy)
			instance.setEmptyInstanceTask(ThreadPoolManager.getInstance().scheduleAtFixedRate(new EmptyInstanceCheckerTask(instance), 60000, 60000));

		log.info("Created new instance: " + worldId + " [" + instance.getInstanceId() + "] owner:" + ownerId + " difficultyId:" + difficultyId);
		return instance;
	}

	public static WorldMapInstance getNextAvailableInstance(int worldId, int ownerId, byte difficult, int maxPlayers, boolean autoDestroy) {
		return getNextAvailableInstance(worldId, ownerId, difficult, null, maxPlayers, autoDestroy);
	}

	public static WorldMapInstance getNextAvailableInstance(int worldId, Player player) {
		int maxPlayers = DataManager.INSTANCE_COOLTIME_DATA.getMaxMemberCount(worldId, player.getRace());
		WorldMapInstance instance = getNextAvailableInstance(worldId, 0, (byte) 0, null, maxPlayers, true);
		instance.register(player.getObjectId());
		return instance;
	}

	public static WorldMapInstance getNextAvailableInstance(int worldId, byte difficult, int maxPlayers) {
		return getNextAvailableInstance(worldId, 0, difficult, null, maxPlayers, true);
	}

	/**
	 * Instance will be destroyed All players moved to bind location All objects - deleted
	 */
	public static void destroyInstance(WorldMapInstance instance) {
		if (instance.getEmptyInstanceTask() != null)
			instance.getEmptyInstanceTask().cancel(false);

		int worldId = instance.getMapId();
		WorldMap map = World.getInstance().getWorldMap(worldId);
		if (!map.isInstanceType())
			return;
		int instanceId = instance.getInstanceId();

		map.removeWorldMapInstance(instanceId);

		log.info("Destroying " + instance);

		TemporarySpawnEngine.onInstanceDestroy(instance); // first unregister all temporary spawns, then despawn mobs
		for (VisibleObject obj : instance) {
			if (obj instanceof Player player) {
				PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_FORCE(0));
				moveToExitPoint(player);
			} else {
				obj.getController().delete();
			}
		}
		instance.getInstanceHandler().onInstanceDestroy();
		WalkerFormator.onInstanceDestroy(worldId, instanceId);
	}

	public static WorldMapInstance getOrRegisterInstance(int worldId, Player player) {
		WorldMapInstance instance = getRegisteredInstance(worldId, player.getObjectId());
		if (instance == null)
			instance = getNextAvailableInstance(worldId, player);
		return instance;
	}

	public static WorldMapInstance getRegisteredInstance(int worldId, int objectId) {
		for (WorldMapInstance instance : World.getInstance().getWorldMap(worldId)) {
			if (instance.isRegistered(objectId))
				return instance;
		}
		return null;
	}

	/**
	 * @return Instance for the given house or studio.
	 */
	public static WorldMapInstance getOrCreateHouseInstance(House house) {
		WorldMapInstance instance = house.getPosition() == null ? null : house.getPosition().getWorldMapInstance();
		if (instance == null && house.getBuilding().getType() == BuildingType.PERSONAL_INS) { // studio
			instance = getOrCreatePersonalInstance(house.getAddress().getMapId(), house.getOwnerId());
		}
		if (instance == null) // should never happen since only studios are spawned on demand
			throw new NullPointerException(house + " has no instance");
		return instance;
	}

	private static WorldMapInstance getOrCreatePersonalInstance(int worldId, int ownerId) {
		if (ownerId == 0 || !WorldMapType.getWorld(worldId).isPersonal())
			return null;

		for (WorldMapInstance instance : World.getInstance().getWorldMap(worldId)) {
			if (instance.isPersonal() && instance.getOwnerId() == ownerId)
				return instance;
		}
		return getNextAvailableInstance(worldId, ownerId, (byte) 0, 0, true);
	}

	public static void onPlayerLogin(Player player) {
		int worldId = player.getWorldId();
		int ownerId = player.getCommonData().getWorldOwnerId();
		WorldMapInstance instance = ownerId != 0 ? getOrCreatePersonalInstance(worldId, ownerId) : getRegisteredInstance(worldId, player.getObjectId());
		if (instance == null && player.getWorldMapInstance().getTemplate().isInstance() || instance != null && instance.isFull())
			moveToExitPoint(player);
		else if (instance != null) // set to correct instanceId (default on login is 1)
			World.getInstance().setPosition(player, worldId, instance.getInstanceId(), player.getX(), player.getY(), player.getZ(), player.getHeading());
		player.getWorldMapInstance().getInstanceHandler().onPlayerLogin(player);
	}

	public static void moveToExitPoint(Player player) {
		TeleportService.moveToInstanceExit(player, player.getWorldId(), player.getRace());
	}

	public static boolean instanceExists(int worldId, int instanceId) {
		return World.getInstance().getWorldMap(worldId).getWorldMapInstance(instanceId) != null;
	}

	private static class EmptyInstanceCheckerTask implements Runnable {

		private final WorldMapInstance worldMapInstance;
		private final long taskStartTime;

		private EmptyInstanceCheckerTask(WorldMapInstance worldMapInstance) {
			this.worldMapInstance = worldMapInstance;
			this.taskStartTime = System.currentTimeMillis();
		}

		private boolean canDestroyInstance() {
			if (!worldMapInstance.getPlayersInside().isEmpty())
				return false;
			return worldMapInstance.isPersonal() || isRegisteredTeamDisbanded() || System.currentTimeMillis() > calculateDestroyTime() - 1000;
		}

		private boolean isRegisteredTeamDisbanded() {
			GeneralTeam<?, ?> registeredTeam = worldMapInstance.getRegisteredTeam();
			return registeredTeam != null && registeredTeam.isDisbanded();
		}

		private long calculateDestroyTime() {
			long lastActivity = Math.max(taskStartTime, worldMapInstance.getLastPlayerLeaveTime());
			return lastActivity + getDestroyDelaySeconds(worldMapInstance) * 1000;
		}

		@Override
		public void run() {
			if (canDestroyInstance())
				destroyInstance(worldMapInstance);
		}
	}

	public static void onLogout(Player player) {
		player.getPosition().getWorldMapInstance().getInstanceHandler().onPlayerLogout(player);
	}

	public static void onEnterInstance(Player player) {
		player.getPosition().getWorldMapInstance().getInstanceHandler().onEnterInstance(player);
		AutoGroupService.getInstance().onEnterInstance(player);
	}

	public static void onLeaveInstance(Player player) {
		WorldMapInstance instance = player.getWorldMapInstance();
		instance.getInstanceHandler().onLeaveInstance(player);
		if (instance.getRegisteredCount() > 0) {
			if (instance.getMaxPlayers() == 1) // solo instance
				PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE(getDestroyDelaySeconds(instance) / 60));
			else if (instance.getRegisteredTeam() != null && instance.getRegisteredTeam().getMembers().isEmpty())
				PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_PARTY(0));
			else if (instance.getPlayersInside().size() <= 1)
				PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_PARTY(getDestroyDelaySeconds(instance) / 60));
		}

		if (AutoGroupConfig.AUTO_GROUP_ENABLE)
			AutoGroupService.getInstance().onLeaveInstance(player);
	}

	public static void onEnterZone(Player player, ZoneInstance zone) {
		player.getPosition().getWorldMapInstance().getInstanceHandler().onEnterZone(player, zone);
	}

	public static void onLeaveZone(Player player, ZoneInstance zone) {
		player.getPosition().getWorldMapInstance().getInstanceHandler().onLeaveZone(player, zone);
	}

	public static int getInstanceRate(Player player, int mapId) {
		return player.hasPermission(MembershipConfig.INSTANCES_COOLDOWN) && !InstanceConfig.INSTANCE_COOLDOWN_RATE_EXCLUDED_MAPS.contains(mapId) ? InstanceConfig.INSTANCE_COOLDOWN_RATE : 1;
	}

	public static int getDestroyDelaySeconds(WorldMapInstance worldMapInstance) {
		return worldMapInstance.getMaxPlayers() == 1 ? InstanceConfig.SOLO_INSTANCE_DESTROY_DELAY_SECONDS : InstanceConfig.INSTANCE_DESTROY_DELAY_SECONDS;
	}
}

📎 첨부파일

댓글 작성 권한이 없습니다.
🏆 포인트 랭킹 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