#상점과 상점 설정 창

1 messages · Page 1 of 1 (latest)

ancient wasp
#

유저가 기본적으로
상호작용할 수 있는 상점 인벤토리가 있고

해당 인벤토리는 유저가 구매/판매를
하는 용도이며 모든 InventoryClickEvent가
캔슬 됩니다.

다만 관리자가 해당 상점 인벤토리에
원하는 아이템을 배치하기 위해서
InventoryClickEvent가 캔슬되지 않도록 해야하는데

따로 상점을 제작할때
관리자용 인벤토리까지 새로 만들어서
해당 인벤토리에서 InventoryClickEvent가
캔슬되지 않으며, 관리자용 인벤토리를
닫을때 그 인벤토리의 Contents가

유저들이 상호작용하기 위해 있는
상점 인벤토리에 적용되는 방식을 생각해봤지만
이 방식은 제가 느끼기엔
너무 원초적인 방식이 아닐까 싶습니다..

혹시 더욱 개선된 방식이 있을까요?

sharp delta
#
    @EventHandler
    public void onClick(InventoryClickEvent event) {
        HumanEntity player = event.getWhoClicked();
        //인벤토리 확인 및 예외 처리
        if (player.isOp()) { //관리자일 경우(+필요 시 수정 상태일 경우 추가)
            //인벤토리 아이템 배치 가능
            return; //상호작용을 방지하기 위한 코드
        }
        //아이템 상호작용 코드
        event.setCancelled(true);
    }

위 코드가 일반적인 코드라고 생각합니다.
인게임에서 상점 인벤토리를 처음 만드는게 아닌 이상 굳이 관리자용 인벤토리가 필요없다고 생각합니다.

관리자용 인벤토리에서 배치를 수정 후에 변경 사항을 유저들이 쓰는 상점 인벤토리에 반영시켜주는 것보단 위 코드처럼 상태를 체크해서 유저는 유저대로 상점을 이용하고 관리자는 수정하고 싶으면 수정할 수 있게 해주는게 더 깔끔한 거 같네요.

gloomy ruin
#

전 유저용과 관리자용은 무조건 따로 있어야한다고 봅니다

sharp delta
#

관리자용 인벤토리가 필요한거면 질문자님이 말씀하신 방법대로 하는게 무난하긴해요 아마 UI 때문에 그런 거 같은데

ancient wasp
# sharp delta ```java @EventHandler public void onClick(InventoryClickEvent event) { ...

답변 감사합니다.
하지만 제가 구현하려는 상점 플러그인에서 해당 방식을 사용하기에는 무리가 있는거같더군요.
설명을 자세히 안해놨네요.

상점에 페이지 개념도 따로 존재하기때문에 List<Inventory>를 통하여 제작되었으며
관리자도 상점과 기본적으론 상호작용 가능하고 편집 상태일때만 따로 수정 가능하게 하려고 합니다.
다만 그렇게 하려면 예제로 보여주신 방법처럼, 퍼미션같이 조건 또는 권한이 있을때를 감지하여
ex: /상점 편집 상점이름 -> 을 통해 상점을 열었을때 일정 권한을 주고,
권한이 있는 대상을 기준으로 InventoryClickEvent에서 하지 않으며
해당 인벤토리를 닫았을때 권한을 제외해주면 하나의 인벤토리로
관리가 가능해지겠지만

앞서 말씀드린것처럼 페이지 개념을 구현해둔 터라
페이지를 넘어갈때 List<Inventory>의 다음 index를 openInventory 해주기 때문에
원래 존재하던 인벤토리가 닫히는 판정이라서 이 방법은 안될것같다고 판단했습니다..

ancient wasp
gloomy ruin
#

관리자가 설정한 데이터를 유저 상점 인벤에 단순히 띄워주면 되는거라서용

gloomy ruin
#

아이템이 List<ItemStack>이면 현재 페이지를 인식해서 List<ItemStack>을 잘라서 보여주면 됩니다

ancient wasp
ancient wasp
# gloomy ruin 아이템이 List<ItemStack>이면 현재 페이지를 인식해서 List<ItemStack>을 잘라서 보여주면 됩니다

음.. 그럼
(상점 인벤토리가 6줄 고정이라는 전제 하에)
ItemStack List 54칸어치마다 인벤토리를 하나씩
만들어서 ItemStack List를 잘라 배치해주는걸 말씀하신건가요?

현재 페이지 개념은 List<Inventory>에
페이지 값(int)만큼의 인벤토리를 추가해주고
InventoryHolder를 통해 해당 인벤토리의
고유 상점ID와 페이지 값을 인벤토리 자체에
저장해주는 방식을 사용하였습니다.

말씀하신 바로는 페이지를 인식하여
List<ItemStack>을 잘라서 보여준다는게
위에서 말한 방법인지 아님 다른 방법인지 감이 안잡혀서..
안바쁘시다면 혹시 간단한 예제같은거라도 가능할까요?

gloomy ruin
# ancient wasp 음.. 그럼 (상점 인벤토리가 6줄 고정이라는 전제 하에) ItemStack List 54칸어치마다 인벤토리를 하나씩 만들어서 ItemStack...
class GiftBoxView(
    private val inventorySetting: InventorySetting,
    private val giftBox: GiftBox
) : HQContainer(54, inventorySetting.title) {

    private var page = 0

    private val giftSlots = inventorySetting.getSlots(SlotType.GIFT) // 1칸~45칸
    private val giftSize = giftSlots.size // 45개

    private val itemStacks get() = giftBox.getItemStacks() // 모든 아이템
    private var currentItemStacks = emptyList<ItemStack>() // 현재 페이지 아이템

    override fun initialize(inventory: Inventory) {
        inventory.clear()
        // 페이지와 아이템이 보여질 슬롯 계산해서 자르기
        // drop은 List 앞에 있는 데이터를 숫자만큼 제외하고
        // take는 List 앞에 있는 데이터를 숫자만큼 잘라서 새로운 List를 반환합니다
        currentItemStacks = itemStacks.drop(giftSize * page).take(giftSize)
        giftSlots.forEachIndexed { index, slot ->
            if (index >= currentItemStacks.size) return
            val itemStack = currentItemStacks.getOrNull(index) ?: return@forEachIndexed
            inventory.setItem(slot, itemStack)
        }
    }

    override fun onClick(event: InventoryClickEvent) {
        val player = event.whoClicked as Player
        val slot = event.rawSlot
        val slotType = inventorySetting.findSlotTypeBySlot(slot) ?: return
        when (slotType) {
            SlotType.BEFORE_PAGE -> {
                if (page == 0) return
                page--
                refresh()
            }
            SlotType.NEXT_PAGE -> {
                if (itemStacks.size <= (page + 1) * giftSize) return
                page++
                refresh()
            }
            SlotType.GIFT -> {}
        }
    }
}
#

코틀린이긴 한데 전 이런 느낌으로 씁니다

#

인벤토리 하나에서 페이지 기능만 구현해주면
인벤토리 여러개를 넘나들 필요가 없이 자연스럽게 넘어가고 아이템 구매/판매가 되겠져

ancient wasp
#

오.. 친절히 설명해주셔서 정말 감사하지만 코틀린으로 짜본적이 없어서 이게 참..

HQContainer는 자바로 치면 구현해두신 클래스 따로 extends를 통해 받아오신거고
GiftBox, InventorySetting도 따로 만들어두신 클래스/인터페이스겠죠?

요컨대 이론만 따지자면 하나의 인벤토리에 따로 페이지 구념을 구현하고
ItemStack List를 해당 인벤토리의 사이즈만큼 잘라서 넣어준 뒤
페이지를 넘어갈 때 인벤토리를 클리어 후 그 다음 ItemStack을 배치해주는 개념이.. 되는건가요?

ancient wasp
#

아 InventoryHolder를 implements 받은 클래스 만들어두시고 그걸 extends로 받아오신거군요

#

정말 감사합니다 선생님 해당 방식으로 시도해보겠습니다

ancient wasp
#

한가지 궁금한게 생겨서 질문드립니다.

상점 ID와 상점 표기 제목을 따로 나누려고 하는데
상점 ID는 그냥 명령어를 실행할때 입력하는 key값이며
표기 제목은 말 그대로 상점 인벤토리를 열었을때 보여지는 인벤토리 이름입니다.

현재는 List<ItemStack>를 사용함으로써 상점ID가 곧 표기제목이지만
따로 상점 인벤토리 제목을 바꿀 수 있는 방식을 사용하고싶습니다.

생각해둔 방법은
따로 Shop 클래스를 만들어 둔 뒤
private String title; (상점 표기 제목)
private List<ItemStack> itemStacks; (상점아이템)
을 선언하고
getter를 이용하여 가져오는 메서드를 만들어둔 뒤
HashMap<String, Shop>으로 저장해서 getTitle을 통하여
상점 인벤토리를 열때 title값을 제목으로 하는 방식을 생각하고있습니다.

혹시 더 좋은 방법이 있을까요?

gloomy ruin
ancient wasp
#

네네 shop 클래스엔 상점에 넣을 List<ItemStack>와 상점 표기제목을 정할 String title이 있습니다

맵의 key는 상점ID로 이용합니다.

ancient wasp
#

아 그냥 제가 말한게 정배 방법이라 말씀하신건가