Aldar-Player-Manage 문서입니다.
1. Features
- 각 서버별 플레이어 캐시 데이터 분산저장 & 동기화
- 플레이어의 입장/퇴장/서버이동 옵저버 제공
- Permissons(권한), Chat Message(메세지), Server Switch(서버이동) 관련 API 제공
- 프록시 또는 마인크래프트 서버의 서버다운 핸들링 , 2개이상의 프록시 호환
2. Mechanism
2.1 서버 연결 흐름도
- 플레이어 접속시 시나리오 (Player Server Join)
- 플레이어 퇴장시 시나리오 (Player Proxy Quit)
- 플레이어 서버이동시 시나리오 (Player Server Switch Join)
2.2 Proxy/Minecraft 서버 다운시
- 프록시서버 다운시 게임서버는 해당 Proxy를 경유해서 접속한 플레이어의 캐시데이터(IAldarPlayer)를 삭제한다.
- 프록시 서버 재개시 다른 프록시 서버로부터 캐시데이터를 전송받는다. (단일 프록시 사용시 문제되지않음)
- 마인크래프트 서버 다운시 게임서버와 프록시서버는 해당 서버의 플레이어의 캐시데이터(IAldarPlayer) 를 삭제한다.
- 마인크래프트 서버 재개시 프록시 서버로 부터 캐시데이터를 전송받는다.
3. AldarPlayerManageAPI
PlayerManageAPI를 사용하기위해 Paper(Bukkit)환경에서 다음과 같은 방식으로 가져올수 있습니다.
try
{
IAldarPlayerManageAPI playerApi = DependencyLoader
.<PlayerManagerCore>getPluginInst("aldar-player-manage-v2")
.getAldarPlayerManageAPI();
} catch (Exception e)
{
this.logger.log(Level.SEVERE, "플러그인 의존성 로드 실패:");
}
Aldar-Player-Manage 를 로드하기 위해서는 Aldar-framework 를 디펜던시로 필요합니다.
해당 API는 다음과 같은 기능을 제공합니다.
public interface IAldarPlayerManageAPI
{
/**
* UUID 통해 플레이어의 정보를 가지고 옵니다.
* @param uuid
* @return
*/
public IAldarPlayer getAldarPlayer(UUID uuid);
/***
* username 을 통해 플레이어의 정보를 가지고 옵니다.
* @param userName
* @return
*/
public IAldarPlayer getAldarPlayer(String userName);
/**
* 글로벌 전체 플레이어의 목록을 가져옵니다.
* @return
*/
public Map<UUID, IAldarPlayer> getAldarPlayerMap();
/**
*
* @return
*/
public List<UUID> getAldarPlayerUUIDs();
/**
* 글로벌 서버의 옵저버를 등록합니다 (다른 서버들의 플레이어 입장/퇴장/변경 을 알수있습니다.)
* @param observer
*/
public void addGlobalPlayerConnObserver(GlobalPlayerConnectionObserver observer);
/**
* 글로벌 서버의 옵저버를 삭제합니다.
* @param observer
*/
public void removeGlobalPlayerConnObserver(GlobalPlayerConnectionObserver observer);
/**
* 로컬 서버의 옵저버를 삭제합니다.
* 현재 서버내에 있는 플레이어의 입장/퇴장/변경 만을 알수있습니다.
* @param observer
*/
public void addLocalPlayerConnObserver(LocalPlayerConnectionObserver observer);
/**
* 로컬 서버의 옵저버를 삭제합니다.
* @param observer
*/
public void removeLocalPlayerConnObserver(LocalPlayerConnectionObserver observer);
/**
* 플레이어를 다른 서버로 이동시킵니다.
* @param uuid
* @param targetServer
* @return
*/
public void jumpServer(UUID uuid, String targetServer);
public void jumpServer(UUID uuid, AldarLocation location);
public void jumpServer(UUID uuid, AldarLocation location, Consumer<Boolean> callback);
public void jumpServer(UUID uuid, String targetServer, String worldname , double x , double y , double z);
public void jumpServer(UUID uuid, String targetServer, String worldname , double x , double y , double z , float yaw , float pitch);
public void jumpServer(UUID uuid, String targetServer, Consumer<Boolean> callback);
public void jumpServer(UUID uuid, String targetServer, String worldname , double x , double y , double z, Consumer<Boolean> callback);
public void jumpServer(UUID uuid, String targetServer, String worldname , double x , double y , double z , float yaw , float pitch , Consumer<Boolean> callback);
/***
* 해당 플레이어들에게 동일한 메세지를 보냅니다.
* @param players
* @param message
*/
public void sendMessageMulticast(List<IAldarPlayer> players, String message);
public void sendMessageMulticastUUID(List<UUID> players, String message );
public void sendMessageMulticastPlayerName(List<String> players, String message);
public void sendMessageBroadCast(String message);
/**
* 로비 좌표를 가져옵니다.
* @return
*/
public AldarLocation getLobbyLocation();
/**
* 처음 접속한 유저가 접속하는 장소를 가져옵니다.
* @return
*/
public AldarLocation getFirstJoinLocation();
}
4. Observer
다른서버 또는 같은서버내에서 플레이어의 접속/퇴장/서버이동을 처리하기위해 사용합니다.
4.1 Local Observer
public interface LocalPlayerConnectionObserver
{
/**
* AldarLocalPlayerAsyncPreLoginEvent
* 플레이어가 접속하기 전에 호출됩니다.
*
* 보통 DB에서 데이터를 읽어올때 사용합니다.
*
* <Default Join & First Join>
* 현재서버에서 읽어온 값을 JsonObject에 저장하면 다른서버의 Global Observer에서 JsonObject가 브로드캐스트됩니다.
* <ServerSwitch Join>
* 이전 서버에서 보낸 JsonObject를 가져올수 있습니다.
*
* Disallow 메서드호출시 해당플레이어의 서버접속이 취소 됩니다.
*
* @param e
*/
public void onPlayerJoin(AldarLocalPlayerAsyncPreLoginEvent e);
/**
* AldarLocalPlayerJoinEvent
* 플레이어가 현재서버에 접속했을때 호출됩니다.
*
* <Default Join & First Join>
* AldarLocalPlayerAsyncPreLoginEvent 에서 저장한 JsonObject를 가져올수 있습니다.
* <ServerSwitch Join>
* 이전 서버에서 보낸 JsonObject를 가져올수 있습니다.
*
* @param e
*/
public void onPlayerJoin(AldarLocalPlayerJoinEvent e);
/**
* AldarLocalPlayerQuitEvent
* 플레이어가 현재서버를 나갈때 호출됩니다.
*
* <Proxy Quit & Server Switch Quit>
* 임시로 JsonObject에 데이터를 저장하고 이후
* public void saveAsyncDB(Consumer<JsonObject> task)
* 를 통해서 DB작업을 따로 수행할수 있습니다.
*
* @param e
*/
public void onPlayerLeave(AldarLocalPlayerQuitEvent e);
/**
* AldarLocalPlayerTeleportEvent
* 플레이어가 텔레포트할때 호출됩니다.
* @param e
*/
public void onPlayerTeleport(AldarLocalPlayerTeleportEvent e);
}
<옵저버 등록>
this.playerApi.addLocalPlayerConnObserver(/*LocalPlayerConnObserver 을 구현한 클래스*/);
<예제>
public class LocalObserverExample implements LocalPlayerConnectionObserver
{
/**
* AldarLocalPlayerAsyncPreLoginEvent 에서는 DB에서 데이터를 가지고 온다
* 저장한 데이터를 임시로 JsonObject 에 담는다.
* DB에서 가져온 데이터는 AldarLocalPlayerJoinEvent 에서 수행할것
*/
@Override
public void onPlayerJoin(AldarLocalPlayerAsyncPreLoginEvent e)
{
JoinResult r = e.getResult();
IAldarPlayer info = e.getPlayer();
switch(r)
{
case DEFAULT_JOIN:
//do something
break;
case FIRST_JOIN:
//do something
break;
case SERVER_SWITCH_JOIN:
String beforeServer = e.getBeforeServer();
JsonObject obj = e.getJsonObject(); //커스텀 메세지
break;
}
//접속하기 전에 차단 가능
e.disallow("<테스트> 에러발생");
}
@Override
public void onPlayerJoin(AldarLocalPlayerJoinEvent e)
{
JoinResult r = e.getResult();
IAldarPlayer info = e.getPlayer();
Player player = e.getBukkitPlayer();
AldarLocation loc = e.getPreDeterminedLocation();
switch(r)
{
case DEFAULT_JOIN:
//do something
break;
case FIRST_JOIN:
//do something
break;
case SERVER_SWITCH_JOIN:
//커스텀 메세지
JsonObject obj = e.getJsonObject();
break;
}
}
/**
* 구문안에서 동기로 DB처리 할것
*/
@Override
public void onPlayerLeave(AldarLocalPlayerQuitEvent e)
{
QuitResult r = e.getResult();
switch(r)
{
case PROXY_QUIT:
Player p1 = e.getBukkitPlayer();
JsonObject obj = e.getMessage();
obj.addProperty("player_status", "dead");
// 버킷스레드에서 동기화할 데이터를 JSON 으로 임시 저장 <Bukkit Thread>
e.saveAsyncDB(json -> {
//DB 작업 수행 <Async Thread>
String status = obj.get("player_status").getAsString();
});
break;
case SERVER_SWITCH_SAVE: //DB작업 수행
Player p2 = e.getBukkitPlayer();
e.saveAsyncDB(json -> {
//DB 작업 수행 <Async Thread>
//TargetServer로 실을 커스텀 메세지 JSON으로 저장
json.addProperty("hello", "good");
});
break;
case SERVER_SWITCH_QUIT: //내부 캐시 지울때 사용
//remove local cache
break;
}
}
@Override
public void onPlayerTeleport(AldarLocalPlayerTeleportEvent e)
{
TeleportResult r = e.getResult();
switch(r)
{
case TELEPORT_AFTER:
//do something
break;
case TELEPORT_BEFORE:
//do something
break;
}
}
}
4.2 Global Observer
public interface GlobalPlayerConnectionObserver
{
public void onPlayerJoin(AldarGlobalPlayerJoinEvent e);
public void onPlayerQuit(AldarGlobalPlayerQuitEvent e);
}
<옵저버 등록>
this.playerApi.addGlobalPlayerConnObserver(/*GlobalPlayerConnObserver 을 구현한 클래스*/);
'마인크래프트 > 플러그인 개발' 카테고리의 다른 글
플레이어 정보 공유 (Aldar-Share) (0) | 2021.12.15 |
---|---|
월드 분할 시스템 (Aldar-World-Division) (3) | 2021.12.15 |
알다르 프로젝트 서버 구조 (0) | 2021.12.12 |
PROJECT ALDAR (0) | 2021.12.12 |
Quest - 범용 퀘스트 플러그인 (0) | 2020.03.29 |