Skip to content
Dr_Romantic edited this page Aug 21, 2020 · 3 revisions

Thread(스레드): 프로그램에서 독립적으로 처리하는 하나의 작업 단위

현재의 트리거 코드 디자인 방식은 서버에서 처리하는 스레드에 포함된 것이 아닌 트리거 리엑터만의 독립된 스레드에서 실행합니다. 즉, 서버에서 처리하는 스레드에 들어가 있지 않기 때문에, 실질적으로 서버에서 일어나는 이벤트를 취소할 수가 없습니다. 이를 해결하기 위해서, 그리고 그 외 다른 기능을 활용하기 위해서, Sync Mode 기능이 트리거에 추가되었습니다.

Sync Mode 로 설정되어 있는 구문은 TR만의 독립된 스레드가 아닌 서버 자체 스레드에서 실행되므로, 이벤트를 취소하는 것이 가능하게 됩니다.

다르게 말해서, 서버 스레드를 사용하기 때문에, 구문을 신중하게 작성하셔야 합나다. 잘못 작성하면 서버 스레드를 모조리 빨아먹어 서버에 지연(렉, 백섭등)이 발생할 수 있습니다!

Named Trigger을 제외한 나머지 종류의 모든 트리거들은 기본적으로 Async로 실행됩니다. 즉 이벤트를 취소하고 싶다면 사용자가 직접적으로 Sync Mode로 번경 해줘야 Sync Mode를 실행할 수 있습니다. 이벤트를 취소하는 것 외에도 Bukkit API에 직접 접근하는 등의 행동을 할때도 Sync Mode가 필요한 경우가 있어 Sync모드 실행법은 꼭 숙지해야 할 것중 하나입니다.

Sync Mode의 반댓말은 Async Mode입니다. 즉 Async Mode는 TR만의 독립된 스레드에서 실행되는 것 입니다.

Sync / Async Mode 설정하기 (켜기/끄기)

구문 자체에서 Sync Mode를 켜고, 끄는 것은 몇몇의 트리거만 가능합니다.

Area Trigger에서 Sync Mode로 전환하기

/trg a MyArea sync

위 명령은 "MyArea" 라는 이름을 가진 Area Trigger을 Sync Mode로 전환합니다.

Custom Trigger에서 Sync Mode로 전환하기

/trg sync MyCustomTrigger

위 명령은 "MyCustomTrigger" 라는 이름을 가진 Custom Trigger을 Sync Mode로 전환합니다.

Named Trigger에서 "Async" Mode 로 전환하기

#CALL "MyNamedTrigger" false

이 구문은 처음 들어보실 수 있습니다. 분명 #CALL은 뒤에 Named Trigger 이름 하나만 오는것이 정상인데, 왜 false라는게 붙었을까요? 사실 #CALL 뒤에는 값으로 하나가 더 올 수 있습니다. 앞에서 언급했다시피, Named Trigger 은 기본적으로 Sync Mode로 실행됩니다. 즉 Async Mode 로 바꿔주기 위해서는 우리가 다른 트리거에서 Sync Mode로 바꿔주듯이 수동적으로 바꿔주어야 합니다. 그 방법이 바로 #CALL 에서 Named Trigger 이름 뒤에 boolean 값을 하나 더 붙이는 것 입니다. 그 boolean값이 의미하는 것은 Sync Mode의 적용 여부입니다. 즉, true는 Sync를 적용한다는 것이고, false는 Sync를 미적용, 즉 Async로 돌아간다는 것 입니다. 이때 기본값은 true이기 때문에 true는 생략해도 되는 것 입니다. 즉, 위 구문은 "MyNamedTrigger" 이라는 이름을 가진 네임드 트리거를 Async Mode로 불러옵니다.

#CANCELEVENT Executor

#CANCELEVENT Executor 는 Sync Mode에서만 사용할 수 있습니다.

#CANCELEVENT

위 간단한 구문은 그 구문과 관련된 이벤트를 취소시킵니다.

만약에 #CANCELEVENT Executor 가 AreaTrigger의 ENTER 내부에 위치해 있다면, 그 구역은 나갈수는 있지만 들어갈 수는 없습니다. ENTER에서 #CANCELEVENT 를 실행하면 플레이어가 움직이는 이벤트 그 자체를 취소시키기 때문에 계속 한자리에 머물게 되고, 이는 그 구역 안으로 들어갈 수 없게 만듭니다.

조금 더 쉽게 생각해봅시다.

우리도 압니다. 지금 여기서 설명하고 있는 Sync/Async, Multi-Threading 모두 외계어처럼 들리죠? 그렇습니다. 이 개념은 너무 어려운 부분입니다. 너무 어렵다면, 이렇게 생각해보는건 어떨까요?

만약 당신이 만든 트리거가 어떤것도 수정하지 않을 때

예를 들어, 당신이 PlayerTeleportEvent를 취소시키고 싶을 때, 이는 유저의 게임 플레이에 직접적인 영향을 미칩니다. 위 예시와 정 반대인 것이 바로 Async Mode비동기 모드 입니다. 비동기 모드는 유저의 게임에 직접적인 영향을 미치지 않을 때, 즉, 당신의 트리거가 아무것도 수정하지 않고 값만 불러오거나 한다고 생각될 경우 비동기 모드가 적합합니다.

만약 당신이 만든 트리거가 한번이라도 플레이에 영향을 미칠 때

예를 들어, 당신이 월드에 새 엔티티를 스폰하고 싶을 때, 알고 있듯이 해당 행위는 절대적으로 자연적인 스폰이 아닌 인공적 스폰입니다. 즉 해당 행위는 유저의 게임 플레이에 직접적인 영향을 미치게 됩니다. Sync모드가 True로 설정되어야 하는 경우의 이유도 비슷합니다. 만약 플레이어의 움직임을 #CANCELEVENT를 통해서 취소하도록 할 때, 이 행위 역시 유저의 게임 플레이에 직접적인 영향을 미칩니다. 이를 위해서는 버킷에서 조정해주어야 하는데 이것을 가능케 해주는 것이 Sync Mode라고 생각하시면 쉽게 이해되실 겁니다.

SYNC/ASYNC 선언구문

SYNC/ASYNC 선언 구문은 Sync Mode와 Async Mode를 사용자가 작성하는 트리거 구문에서 좀 더 자유롭게 조정할 수 있도록 하기 위해서 추가되었습니다. 이 방법에 한가지 단점이 있다면, #STOP , #WAIT , #CANCELEVENT 와 같은 Sync, Async에 각각 기본적으로 배정되어 있는 Executor들은 플러그인 구문 형태 특성상 사용하지 못한다는 것 입니다. 만약 해당 Executor들을 사용하고 싶다면, NamedTrigger 사용을 고려해보세요.

SYNC 선언구문

일반적으로, SYNC 선언구문은 SYNC 그 자체와 ENDSYNC 사이에 있는 구문을 서버 스레드에서 실행(Sync Mode로써 실행)합니다. 만약 이 구문이 이미 Sync Mode로 설정된 트리거 구문에서 사용될 경우, 똑같이 Sync Mode로써 실행되서 실질적으로 선언의 의미가 없습니다. 참고로 Sync모드에서는 서버 스레드의 특성에 따라 모든 구문이 동시 실행 됩니다. 다음 예문을 봐주세요.

예문:

SYNC
    #MESSAGE "1"
    #MESSAGE "2"
    #MESSAGE "3"
ENDSYNC

위 예문은 1, 2, 3을 동시에 채팅창에 출력합니다.

ASYNC 선언구문

일반적으로, ASYNC 선언구문은 ASYNC 그 자체와 ENDASYNC 사이에 있는 구문을 TR만의 독립된 스레드에서 실행(Async Mode로써 실행)합니다. 만약 이 구문이 이미 Sync Mode로 설정된 트리거 구문에서 사용될 경우, 똑같이 Async Mode로써 실행되서 실질적으로 선언의 의미가 없습니다. 참고로 Async모드에서는 TR만의 스레드 특성에 따라 모든 구문이 차례대로 실행됩니다. 다음 예문을 봐주세요.

예문:

ASYNC
    FOR x = 0:10
        #MESSAGE x
    ENDFOR
ENDASYNC

위 구문은 0부터 9까지 메시지를 차례대로 출력합니다.

**결과적으로는 Async와 Sync 모두 채팅에 구문에서 입력한대로 출력하지만 주목할 점은 동시성 입니다. Sync모드는 그 특성에 따라 모든 메시지가 마치 한 장문처럼 말그대로 ** 딴! 출력됩니다. 그에 반해서 Async는 동시성이 없기 때문에, 메시지가 한번에 출력되지 않고, 말그대로 주루룩 출력됩니다.

Plugin Description / 목차

1. Getting Started () (рус)

S.L. In-game Editor () (рус)

2. Triggers () (рус)

List and usage of Triggers / 트리거 목록과 사용 방법:

  • List of Executors / 실행자(Executor) 목록

4. Placeholders () (рус)

  • Using PlaceholderAPI / PlaceholderAPI 사용법
  • List of Placeholders / 플레이스 홀더(Placeholder) 목록

5. Conditions () (рус)

  • Creating Conditions / 조건식 만들기
    • Boolean Expressions / 부울 (Boolean) 표현 방법
  • Logical Operators / 연산자 사용법
  • IF statement / IF 조건문
  • Null Checking / Null 검사법
  • Switch Case / Switch Case 조건

6. Variables () (рус)

  • Local Variables / 지역 변수
  • Global Variables / 전역 변수

Advanced

Timings () (рус)

7. Methods () (рус)

  • Using Methods / 메소드 사용법
  • Special Data Types / 특수한 데이터 형식
  • Reading Javadocs / Javadoc 읽기
  • Handling Enum / Enum 데이터 처리
  • Lambda Expresion / Lambda(람다) 식 사용법

8. Array () (рус)

  • Creating an empty array / 빈 배열 만들기
  • Storing data into array / 배열에 데이터값 저장하기
  • Read data from array / 배열에서 데이터 읽기(불러오기)

9. Loops () (рус)

  • WHILE loop / WHILE 반복문
  • FOR loop / FOR 반복문
    • Iterating Collection / Collection 형식의 변수 순회법
    • #BREAK executor / #BREAK 실행자
    • #CONTINUE executor / #CONTINUE 실행자

10. Sync Mode () (рус)

  • #CANCELEVENT executor / #CANCELEVENT 실행자
  • Setting Sync/Async Mode / 동기, 비동기 모드 전환
    • Custom Trigger
    • Area Trigger

11. Custom Executors () (рус)

12. Plugin Access () (рус)

  • Check And Use / 플러그인 존재여부 확인
    • Get Third Party Plugin / 제 3자 플러그인 불러오기
    • Check Eligibility / 호환성 확인하기
    • Use the Plugin / 플러그인 사용하기

13. IMPORT Statement () (рус)

  • Creating new instance / 새 인스턴스 생성하기
  • Accessing static method / 종속 메소드 불러오기
  • Accessing static field / 종속 Enum 불러오기

14. IS Statement () (рус)

  • Understanding / 이해하기
    • Understanding Instance / 인스턴스 이해하기
    • Understanding Superclass / 부모클래스 이해하기
    • Understanding Subclass / 자식클래스 이해하기
  • Using IS Statement / IS조건연산자 사용하기

15. TRY-CATCH Statement () (рус)

  • Understanding TRY-CATCH Exception Handling / TRY-CATCH 예외처리 이해하기

Misc

16. Interface Casting () (рус)

module x.x does not "opens x.x" problem

  • List of Custom Events

Examples

Trigger

Trigger Example () (рус)

More Examples: Bukkit, Sponge

Case Specific

Clone this wiki locally