개인 자료란 (JE)

  서버 커뮤니티

Profile Kobins 대표칭호 없음

Kobins 7e61baba5cec465d89e9b4c5615ae13e

Profile

강좌 자바 에디션(JE) 플러그인 개발

[마시자] 마인크래프트로 시작하는 Java 4강 - 스케줄러(Scheduler)와 명령어 기본 (※미완성)

2020.04.02 조회 수 1544 추천 수 1
분야 플러그인 
장르 개발자 툴 
게임버전 모든버전 
API 스피곳, 페이퍼 

4a182932b8728e287affadf3f6c385bd.png

※ 쓰다 서버운영때문에 잠시 보관함에 뒀었는데 등록됐읍니다 - 즉 아직 미완성인 강좌

마인크래프트로 시작하는 Java 4강 목차

스케줄러와 명령어 기본

스케줄러(Scheduler)란?

주의 : 필자는 사실 스레드(Thread) 기능에 대해 잘 알지 못합니다. 간략하게 씨부릴게요

이제 Paper API 내에서 코드가 실행될 수 있는 구간 중 가장 마지막인, 스케줄러(Scheduler)를 알아보도록 합시다!

실제 프로그래밍에서는 스레드(Thread)라고 하는데, 코드의 흐름을 여러 개로 분할시켜 동시에 여러 작업을 할 수 있도록 하는 기능입니다!

그리고, 이 스레드에는 Thread.sleep(ms)라는 기능이 있는데, 말 그대로 스레드를 일정 시간동안 잠들게 합니다!

그럼 그냥 sleep(ms) 기능을 써서 잠시 멈추면 되지, 왜 굳이 스케줄러나 스레드 같은걸 쓰냐 하실텐데,

Paper API는 스레드 한 개(메인 스레드)를 사용해서 플러그인 구문을 실행합니다.

이게 무슨 소리냐, 만약에 스케줄러 기능을 사용하지 않고 Thread.sleep(ms) 기능을 쓰게 되면, 서버가 진짜로 그 시간동안 멈춰버린다는 소리입니다.

모든 플레이어의 움직임이 멈추고, 모든 월드 랜덤 틱도 멈추고, 몬스터도, 동물들도 전부 그 시간동안 움직이지 않게 됩니다.

즉, 흐름을 따로 만들어서 코드를 실행하고 딜레이를 줘야 Paper 메인 스레드에 영향을 주지 않는다는 말이죠!

그리고 그 흐름을 만들고 실행시키는 방법이 스케줄러(Scheduler입니다!)

스레드(Thread) 있다면서 왜 스케줄러(Scheduler) 씀?

마인크래프트는 틱(Tick) 단위로 작동합니다. 그리고 이 틱은 1틱당 0.05초 (1/20)에 해당하죠.

초당 20번의 동작으로 서버/월드 등을 작동하게 되는데일반적인 프로그래밍 환경에서는 0.001초, 혹은 그 미만 단위로 코드가 실행되기도 하는데, 여기서 문제는 Paper API는 마인크래프트 동작 단위인 초당 20틱에 맞추지 않으면 서버가 터집니다.

농담 아니고 Paper API의 메소드 중 뭐 하나 비동기(async)로 작동시켰다가는 얘가 무슨 행동을 할 지 장담할 수 없어집니다.

그냥 에러 내뱉고 끝나는 거면 양반인데, 그냥 서버를 닫아버리기도 합니다.

그래서, Paper의 그 20틱 단위에 동기화(sync)하기 위해서 Scheduler를 사용합니다! Scheduler는 Paper 틱 단위에 맞춰서 실행되는 스레드 중 하나인데, 사실 Thread.sleep(...)하는 방식과는 조금 다르게 딜레이를 줘야 합니다.

카운트 명령어 만들기

단순하게, 10초 세는 카운트를 만들어보면서 스케줄러에 대한 기본적인 감각을 익혀보죠!

그리고, 이전 강좌에서 너무 명령어를 부실하게 다뤘는데, 사실 기초적인 내용만 말한 것이고, 앞으로 강좌에서 각각 필요한 내용들을 보충할 예정입니다.

그런 기념으로, 명령어에 각종 인자들을 달아봅시다.

fe4a61bf1d25d39c99d21c3bc009e436.png

과거에 작성했던 코드가 나를 반갑게 맞아주네요.

앞으로 여기에 각종 기능을 하나하나 추가해볼건데, 그 때마다 명령어를 하나 새로 만드는건 너무 복잡할 것 같지 않나요?

물론 새로 만드는 것도 연습삼아 해보면 좋겠지만, 우리는 /msj count, /msj hello와 같은 서브 커맨드(sub-command)를 만들어 볼 겁니다!

음, 근데 명령어 정보를 어떻게 받아왔더라...?

4c5849be26ad3635562a0abc959dc39f.png

저렇게 명령어 이름 다음으로 띄어쓰기 단위로 구분해서 args라는 문자열 배열에 담긴다 했었지요!

위와 같은 사진에서, 첫 번째 인자인 Kobins 부분을 가져오려면 args[0], 두 번째 인자인 0을 가져오려면 args[1]과 같이 사용할 수 있습니다.

Q. 어? 근데 왜 숫자를 0부터 셈?
A. 모든 프로그래밍 언어에서는 0부터 숫자를 셉니다. https://nanite.tistory.com/56 논리적으로도 좋다고 함...

아무튼, 배열은 저렇게 번호를 0부터 세는데, 문제가 하나 있습니다.

만약에 명령어를 사용하는 사람이 0번째, 1번째, 2번째, 3번째... 부분부분 입력하는 것을 실수했다면?

eddb4bb5cb88b5b93e2afb1f0c22c70d.png

만약에 플레이어가 /tp 명령어만 치고 끝냈을 때, 우리가 args[0]을 하면 어떤 결과가 벌어질까요?

바로 ArrayIndexOutOfBoundsException 오류가 납니다.

배열의 범위를 벗어난 지점을 참조하려 했을 때 나는 오류인데, 즉 배열 크기보다 더 큰 곳을 접근하면 발생하는 오류입니다.

즉, 플레이어가 인자를 입력하지 않으면 공백으로 주는 것도 아니라 아예 배열 크기가 달라진다는 겁니다.

그래서, 명령어를 작성할 때 배열 크기에 대한 제한을 걸어주고, 특정 위치의 문자를 검사하고, 자료형에 맞는지 검사하는 작업이 별도로 필요합니다.

아! 너무 어렵게 썼나? 아무튼, 천천히 배워가면 되니까, 우리가 할 일은 플레이어 또는 콘솔이 /msj count를 치면 10초 단위로 카운트를 세주는 명령어를 작성해볼 겁니다.

진짜로 명령어 만들기

음... 그 전에, 잠시 명령어를 정리해 봅시다.

5a4a94e23c1ee81304fb94f086d63ca6.png

if(args.length <= 0){ } 라는 내용의 if문을 작성해 주었는데, args.length는 args라는 배열의 길이(크기)를 가져오게 됩니다.

즉, 플레이어가 입력한 명령어의 인자들이 하나도 없을 때(/msj만 입력됐을 때) 중괄호 안의 코드를 실행하게 되겠지요.

그리고, 여러 플러그인을 만져본 분들은 알겠지만, 저렇게 인자를 아무것도 안 치고 플러그인 메인 명령어에 접근하면 보통은 플러그인 명령어에 대한 도움말을 던져주거나, 플러그인의 정보를 채팅에 표시하게 되지요.

여기서, 우리는 이 명령어를 통해 어떤 기능을 할 수 있는지를 알려줄겁니다!

if(args.length <= 0){
sender.sendMessage("§7[SYSTEM]§f MSJ 명령어 사용법");
sender.sendMessage("§e/"+label+" help §f도움말을 표시합니다.");
sender.sendMessage("§e/"+label+" hello §f인사를 해줍니다.");
sender.sendMessage("§e/"+label+" count §f10초 카운트를 셉니다.");
}
  • label은 왜 튀어나옴?
    • 명령어의 이름 부분을 반환하는 데 쓰입니다.
    • 우리가 저번 강좌에서 plugin.yml을 쓸 때, aliases: [mj, 마시자] 와 같이 명령어의 별명을 작성해주었는데, label 변수를 통해 명령어를 실행할 때 입력한 별명을 가져올 수 있습니다.
    • 따라서, 명령어를 /마시자 로 입력했을 때 command.getName()은 기존 명령어 이름인 msj를 가져오고, label은 플레이어가 입력한 별명(alias)인 마시자를 가져오게 됩니다. 
  • §e §7은 어디서 튀어나온거임?
    • 색을 입히는 문자입니다. 일반적인 채팅 환경에서는 를 쓸 수가 없어 보통 &7, &e같이 작성하는 데, 플러그인 내부에서는 §를 사용해야 색이 입혀집니다.
    • 사실 꼼수에 가깝습니다. ChatColor.GRAY+"문자" 를 이용하는 방법도 있습니다. 근데 너무 길어요
    • https://minecraft.gamepedia.com/Formatting_codes#Color_codes

와! 우리가 만들 명령어의 기본 기획을 짰습니다!
/msj hello라 치면 명령어를 친 대상한테 안녕이라고 해 줄 것이고,

/msj count라 치면 서버 전체에 10초 카운트를 세는 메세지를 전송할 것입니다.

※ 쓰다 서버운영때문에 잠시 보관함에 뒀었는데 등록됐읍니다

아직 서버개발 중이라 당분간은 강좌를 올리지 못할 것 같습니다...

여기 다른 분 강좌 좋은 것 많으니 그분들것으로...






1개의 댓글

죄송한데.. 3강 마지막에 코드 마무리 할때, CommandManager 클래스의 마지막 } 뒤에서 에러가 나는데 왜 에러가 나는 걸까요e4863b1728dcf2a868852eafdb369de6.PNG?


뉴스 및 창작물
/files/thumbnails/150/925/003/262x150.crop.jpg?20241123005717

건축

응답하라 1988 ?

팀뉴일리시

2024-11-23

3

/files/thumbnails/761/908/003/262x150.crop.jpg?20241025153749

건축

서울 숭례문(崇禮門) 5

KHC

2024-10-25

2

/files/thumbnails/578/899/003/262x150.crop.jpg?20241010142350

건축

경주 월정교 1

KHC

2024-10-10

2

/files/thumbnails/219/899/003/262x150.crop.jpg?20241009200950

건축

송전탑+도시 2

dbasd12

2024-10-09

2

/files/thumbnails/246/898/003/262x150.crop.jpg?20241008102328

레드스톤

단다단 - 오토노케(オトノケ) | 마인크래프트 노트블럭 커버

노트블럭전문가

2024-10-08

1

/files/thumbnails/348/896/003/262x150.crop.jpg?20241006103035

디도스/봇테러등등을 낚는 방법 4

물귀신

2024-10-06

3

/files/thumbnails/839/895/003/262x150.crop.jpg?20241006021227

SRV레코드는 보안도메인이 아닙니다. [서버오픈시 필독]

물귀신

2024-10-05

4