본문 바로가기

마인크래프트/스크립트

마인크래프트 스크립트 - 우편함 스크립트(플러그인)

728x90
반응형

 

마인크래프트 스크립트 - 우편함 스크립트(플러그인)

 


 

이번에는 명령어로 우편함을 입력하면 우편함을 불러오는 스크립트를 생각하고 있습니다.

우편함이 필요한 이유가 스크립트로 만든 GUI창에 아이템을 올려두고 ESC를 통해 창을 꺼버리면

아이템이 그대로 증발하는 생각지 못한 상황이 나올 수 있기 때문에 필요하고

아이템을 주거나 하는건 서버에 기본적으로 있긴 하겠지만 오프라인 유저에게는

give 명령어로 줄 수 없기 때문에 우편함이 있으면 좋겠다 해서 만들어 보려고 합니다.

 

:: 목표 ::

 

우편함을 만들어보자

 


 

일단 먼저 서버에 접속했을 때 우편함이 설정되어있지 않으면

4행으로 설정했으니 36칸 모두 air로 설정해줍시다.

 

on join:
	if {y.%uuid of player%.우편함::*} is not set:
		loop 36 times:
			set {y.%uuid of player%.우편함::%loop-value%} to air

 

왜 air로 설정하는지는 그냥 설정한거에요. ㅎㅎ

 

 

대충 테스트 loop-index로 테스트 해보니 1부터 36까지 잘나옵니다.

근데 0부터 시작이 아니라서 가끔 헷갈릴 때가 있네요.

그런데 인벤토리 창은 0부터 시작이라는거..

 

command /우편함 [<string>]:
	trigger:
		open chest with 4 rows named "&0%player% 우편함" to player

		loop {y.%uuid of player%.우편함::*}:
			set slot loop-value - 1 of current inventory of player to {y.%uuid of player%.우편함::%loop-value%}

 

여기까지 /우편함 명령어로 우편함 변수를 불러오는 코드를 짜봤어요.

그럼 이제 아이템을 어떻게 줄지, 우편함이 꽉차면 어떻게 할지 구상해봐야겠죠

 

아이템은 이렇게 주도록 합시다.

우편함 변수 1부터 반복문을 통해 검색을 하고 만약 air면 그 자리에 아이템을 대입 그리고 종료

 

command /우편함 [<string>] [<offlineplayer>]:
	trigger:
		if arg 1 is not set:
			open chest with 4 rows named "&0%player% 우편함" to player
			loop {y.%uuid of player%.우편함::*}:
				set slot loop-index parsed as number - 1 of current inventory of player to loop-value
                
        # 플레이어가 손에 들고 있는 아이템을 플레이어의 우편함에 넣습니다.
		if arg 1 is "보내기":
			set {_item} to player's tool
			delete player's tool

			loop {y.%uuid of player%.우편함::*}:
				if loop-value is air:
					set {y.%uuid of player%.우편함::%loop-index%} to {_item}
					exit

 

우편함 변수의 아이템을 우편함 GUI에 세팅하려고 칸을 loop-index로 줬더니 이상하게 숫자가 아니라고 안되길래

그냥 parsed as number로 바꿔줬습니다. 그랬더니 되네요. 그리고 인벤은 0부터 시작이니 -1을 해줬습니다.

 

 

보내기를 통해 강화석을 보냈더니 우편함에 잘 도착했습니다.

이제 아이템을 꺼내면 변수에서 삭제하는 코드를 짜야겠네요. 안그러면 다시 우편함을 열었을 때 아이템이 그대로 있을테니말이죠 근데 코드를 짜다가 생각난건데 플레이어의 인벤토리에서 우편함에 아이템을 넣지 못하도록 하는 코드도 짜야겠습니다. 동시에 하면 되겠네요.

 

on inventory click:
	if iname contains "&0%player% 우편함":
		set {_slotItem} to clicked slot
		set {_slotNumber} to clicked raw slot
		if {_slotNumber} >= 0:
			if {_slotNumber} <= 35:
				message "%{_slotNumber}%, %{_slotItem}%"

 

일단 이렇게 적어봤습니다.

 

 

위 코드처럼 적으면 해당 인벤토리의 0~35번까지 슬롯을 클릭하면 번호와 아이템을 얻을 수 있습니다.

슬롯을 클릭했을 때 아이템을 변수로 받아서 give로 바로 인벤토리로 꽂고 35 이상의 슬롯을 클릭하면

이벤트를 취소해버리면 되겠네요. 그리고 인벤토리가 꽉차면 받을 수 없다는 메시지와 함께 클릭 취소까지

 

on inventory click:
	message "%clicked raw slot%"
	if iname contains "&0%player% 우편함":
		set {_slotItem} to clicked slot
		set {_slotNumber} to clicked raw slot
		if {_slotNumber} >= 0:
			# 우편함 만을 선택했을 때
			if {_slotNumber} <= 35:
				# 공기가 아닌 아이템을 선택했을 때
				if {_slotItem} is not air:
					# 인벤토리가 꽉찼는지 확인
					loop 36 times:
						set {_loop} to loop-value + 1
						if slot {_loop} of current inventory of player is not air:
							add 1 to {_tmp} 

					if {_tmp} is 36:
						cancel event
						message "{@s2} 인벤토리가 꽉찼습니다. 인벤토리를 비우고 다시 시도하세요."
						exit

					else:
						cancel event
						give {_slotItem} to player
						delete slot {_slotNumber} of current inventory of player
						set {_u} to {_slotNumber} + 1
						set {y.%uuid of player%.우편함::%{_u}%} to air
						message "{@s2} 우편함에서 %{_slotItem}% &r을(를) 인벤토리로 가져왔습니다."
						exit

			if {_slotNumber} > 35:
				cancel event

 

음... 이렇게 짜봤는데 인벤토리가 꽉찼는지 아닌지 자꾸 확인이 안되네요.

 

 

그래서 {_tmp}이상인가 해서 message로 보이게 해봤더니

 

 

1, 2 하고 끝나버리네요?

왜지???????????? 아~ 바보같이 +1을 해버렸네요 +35를 해야하는데!!!

 

 

코드를 고치니까 제대로 인벤토리가 꽉차니까 인벤토리가 꽉찼다며 들어오질 않습니다.

근데 문제가 또 생겼네요 이제는 안차도 찼다며 들어오질 않네요.

 

on inventory click:
	message "{@s1} %clicked raw slot%, %clicked slot%"
	if iname contains "&0%player% 우편함":
		set {_slotItem} to clicked slot
		set {_slotNumber} to clicked raw slot
		if {_slotNumber} >= 0:
			if {_slotNumber} <= 35:
				if {_slotItem} is not air:
					# 인벤토리가 꽉찼는지 확인
					set {_tmp} to 0
					loop 36 times:
						set {_loop} to loop-value + 35
						set {_loopItem} to slot {_loop} of current inventory of player parsed as itemtype
						if {_loopItem} is not air:
							add 1 to {_tmp}
							message "%{_loop}%, %{_loopItem}%, %{_tmp}%"

					if {_tmp} is 36:
						cancel event
						message "{@s2} 인벤토리가 꽉찼습니다. 인벤토리를 비우고 다시 시도하세요."
						exit

					else:
						cancel event
						give {_slotItem} to player
						delete slot {_slotNumber} of current inventory of player
						set {_u} to {_slotNumber} + 1
						set {y.%uuid of player%.우편함::%{_u}%} to air
						message "{@s2} 우편함에서 %{_slotItem}% &r을(를) 인벤토리로 가져왔습니다."
						exit

			if {_slotNumber} > 35:
				cancel event
				exit

 

 

??? 코드를 조금 수정해서 인벤토리 슬롯의 아이템을 message로 표시하니까 <none>이 나오네요???

왜지?

 

이유를 모르겠어서 0번부터 돌렸는데 우편함의 아이템은 되고 인벤토리의 아이템은 적용이 안된다.

ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

on inventory click:
	if iname contains "&0%player% 우편함":
		set {_slotItem} to clicked slot
		set {_clickItem} to click item
		set {_slotNumber} to clicked raw slot
		#message "{@s1} raw slot: %{_slotNumber}%, item: %{_clickItem}%, slot: %{_slotItem}%"
		if {_slotNumber} >= 0:
			if {_slotNumber} <= 35:
				if {_slotItem} is not air:
					# 인벤토리가 꽉찼는지 확인
					loop all items in the player's inventory:
						add 1 to {_tmp}
					if player's offhand is not air:
						subtract 1 from {_tmp}
					if player's boots is not air:
						subtract 1 from {_tmp}
					if player's leggings is not air:
						subtract 1 from {_tmp}
					if player's chestplate is not air:
						subtract 1 from {_tmp}
					if player's helmet is not air:
						subtract 1 from {_tmp}
					if {_tmp} is 36:
						cancel event
						message "{@s2} 인벤토리가 꽉찼습니다. 인벤토리를 비우고 다시 시도하세요."
						exit
					else:
						cancel event
						give {_slotItem} to player
						delete slot {_slotNumber} of current inventory of player
						set {_u} to {_slotNumber} + 1
						set {y.%uuid of player%.우편함::%{_u}%} to air
						message "{@s2} 우편함에서 %{_slotItem}% &r을(를) 인벤토리로 가져왔습니다."
						exit

				if clicked raw slot is 35:
					cancel event

			if {_slotNumber} > 35:
				cancel event
				exit

 

그러다가 구글링으로 인벤토리 체크하는 구문을 누가 올렸길래 그냥 가져와서 적용시켰더니

제대로 작동된다

 

 

다음에 우편함이 꽉찼을 때 날짜를 추가해서 제일 늦은 날짜를 제거후 그자리에 넣으면 될듯하다.

그러면 우편함의 아이템에 lore을 추가해서 날짜를 넣어주면! 아이템을 가져갈때는 lore을 제거 후 주면 될듯하다.

 

loop {y.%uuid of player%.우편함::*}:
				if loop-value is air:
					set {_lore::*} to lore of {_item}
					add "&6%now%" to {_lore::*} 
					set {y.%uuid of player%.우편함::%loop-index%} to {_item} with lore {_lore::*}
					exit

 

 

lore 임시 리스트 변수를 만들어서 미리 아이템의 lore을 넣고 추가로 현재 시간을 넣는건 쉬웠는데

이제 아이템을 가져오면 원래대로 해야하니까 음어떻게 한담

 

if {_tmp} is 36:
						cancel event
						message "{@s2} 인벤토리가 꽉찼습니다. 인벤토리를 비우고 다시 시도하세요."
						exit
					else:
						cancel event
						set {_lore::*} to lore of {_slotItem}
						loop {_lore::*}:
							if loop-value contains "오전" or "오후":
								set {_time} to {_lore::%loop-index%}
							else:
								add 1 to {_o}

						# lore를 제거 후 다시 입력
						delete lore of {_slotItem}
						loop {_o} times:
							add {_lore::%loop-value%} to lore of {_slotItem}
					
						# 플레이어에게 지급, 제거
						give {_slotItem} to player
						delete slot {_slotNumber} of current inventory of player
						set {_u} to {_slotNumber} + 1

						set {y.%uuid of player%.우편함::%{_u}%} to air
						message "{@s2} 우편함에서 %{_slotItem}% &r을(를) 인벤토리로 가져왔습니다."
						exit

 

lore를 제거하고 다시 입력하는걸로 했더니 잘 되더군요.

 

이제 오래된 아이템을 제거하는 코드를 짜봅시다.

air가 아닌 아이템이 36개 있으면 아이템이 꽉찬거니까

모든 아이템의 오전 오후가 있는 lore만 받아서 비교하면 되겠죠?

 

그런데 하다보니까 생각보다 귀찮아서

랜덤 정수를 받아서 랜덤으로 제거하는걸로 할게요.

 

정말로 귀찮;

 

# 플레이어가 손에 들고 있는 아이템을 플레이어의 우편함에 넣습니다.
		if arg 1 is "보내기":
			set {_item} to player's tool
			delete player's tool

			loop {y.%uuid of player%.우편함::*}:
				if loop-value is air:
					set {_lore::*} to lore of {_item}
					add "&6%now%" to {_lore::*} 
					set {y.%uuid of player%.우편함::%loop-index%} to {_item} with lore {_lore::*}
					exit
				else:
					add 1 to {_i}

			# 우편함이 꽉참
			if {_i} is 36:
				set {_int} to random integer between 1 to 36
				set {_lore::*} to lore of {_item}
				add "&6%now%" to {_lore::*} 
				set {y.%uuid of player%.우편함::%{_int}%} to {_item} with lore {_lore::*}
				exit

 

 

잘 들어가네요.

우편함에는 언제 아이템이 왔다는 정보는 있으면 좋을테니 그냥 두도록 하고

여기서 마칠게요 이거 생각보다 어렵네요...

 

다음에는 나만의 능력자모드를 만들어보려고 합니다~

 

 

 

 

※ 스크립트 다운로드 ※

 

#!==========================================!#
#!                                          !#
#!              우편함                       !#
#!                                          !#
#!==========================================!#

on join:
	if {y.%uuid of player%.우편함::*} is not set:
		loop 36 times:
			set {y.%uuid of player%.우편함::%loop-value%} to air
			
command /우편함 [<string>] [<offlineplayer>]:
	trigger:
		if arg 1 is not set:
			open chest with 4 rows named "&0%player% 우편함" to player
			loop {y.%uuid of player%.우편함::*}:
				set slot loop-index parsed as number - 1 of current inventory of player to loop-value

		if arg 1 is "test":
			loop {y.%uuid of player%.우편함::*}:
				message "%loop-index%, %loop-value%"

		if arg 1 is "초기화":
			delete {y.%uuid of player%.우편함::0}
			loop 36 times:
				set {y.%uuid of player%.우편함::%loop-value%} to stick

		# 플레이어가 손에 들고 있는 아이템을 플레이어의 우편함에 넣습니다.
		if arg 1 is "보내기":
			set {_item} to player's tool
			delete player's tool

			loop {y.%uuid of player%.우편함::*}:
				if loop-value is air:
					set {_lore::*} to lore of {_item}
					add "&6%now%" to {_lore::*} 
					set {y.%uuid of player%.우편함::%loop-index%} to {_item} with lore {_lore::*}
					exit
				else:
					add 1 to {_i}

			# 우편함이 꽉참
			if {_i} is 36:
				set {_int} to random integer between 1 to 36
				set {_lore::*} to lore of {_item}
				add "&6%now%" to {_lore::*} 
				set {y.%uuid of player%.우편함::%{_int}%} to {_item} with lore {_lore::*}
				exit

on inventory click:
	if iname contains "&0%player% 우편함":
		set {_slotItem} to clicked slot
		set {_clickItem} to click item
		set {_slotNumber} to clicked raw slot
		#message "{@s1} raw slot: %{_slotNumber}%, item: %{_clickItem}%, slot: %{_slotItem}%"
		if {_slotNumber} >= 0:
			if {_slotNumber} <= 35:
				if {_slotItem} is not air:
					# 인벤토리가 꽉찼는지 확인
					loop all items in the player's inventory:
						add 1 to {_tmp}
					if player's offhand is not air:
						subtract 1 from {_tmp}
					if player's boots is not air:
						subtract 1 from {_tmp}
					if player's leggings is not air:
						subtract 1 from {_tmp}
					if player's chestplate is not air:
						subtract 1 from {_tmp}
					if player's helmet is not air:
						subtract 1 from {_tmp}
					if {_tmp} is 36:
						cancel event
						message "{@s2} 인벤토리가 꽉찼습니다. 인벤토리를 비우고 다시 시도하세요."
						exit
					else:
						cancel event
						set {_lore::*} to lore of {_slotItem}
						loop {_lore::*}:
							if loop-value contains "오전" or "오후":
								set {_time} to {_lore::%loop-index%}
							else:
								add 1 to {_o}

						# lore를 제거 후 다시 입력
						delete lore of {_slotItem}
						loop {_o} times:
							add {_lore::%loop-value%} to lore of {_slotItem}
					
						# 플레이어에게 지급, 제거
						give {_slotItem} to player
						delete slot {_slotNumber} of current inventory of player
						set {_u} to {_slotNumber} + 1

						set {y.%uuid of player%.우편함::%{_u}%} to air
						message "{@s2} 우편함에서 %{_slotItem}% &r을(를) 인벤토리로 가져왔습니다."
						exit

			if {_slotNumber} > 35:
				cancel event
				exit

 

이번에는 그냥 코드를 올리겠습니다.

 


 

:: 해당 서버에서 사용된 애드온 ::

 

Skript

GomSK

InvSk

GameAPI

HolographicDisplaysAddon

MarSK

QuarSk

SharpSK

SkChoke

Skellett

SkExtras

SkQuery

skRayFall

skript-yaml

SkRPG

SkStuff

skUtilities

TuSKe

Umbaska

Vault

 

만약 코드를 적용했는데 서버에서 에러가 뜨면 애드온 미적용 때문일 확률이 높습니다.

애드온은 아래 사이트에서 대부분 받을 수 있으며 없는 애드온은

아마 한국인 개발자가 만든 애드온일 확률이 높습니다.

구글이나 네이버에 애드온 모음을 검색하면 나와있으니 찾아서 다운로드 하시거나

제 블로그 마인크래프트 항목 처음 글에 다운로드 링크가 걸려있으니 확인하시길 바랍니다.

 

 

 

 

:: 이 글은 원 출처만 남기면 언제든 퍼가고 수정하셔도 좋습니다 ::

 

 

 

728x90
반응형