잡다한 개발/마크플러그인

마크 가챠 4편

오잎 클로버 2021. 11. 25. 15:10
728x90

지난번에는 가챠 상자를 정의하고 가챠 상자 이벤트를 만들 준비를 끝냈습니다.

이제 가챠 상자에서 나오는 오브젝트들을 선택하고 나오도록 만들겠습니다.

그리고 실제로 작동하도록 하겠습니다.

실제로 작동하도록 하는 것은 그리 어렵지는 않지만, 이를 기반으로 세팅하는 것은 자바로 직접적으로 연결이 되어있기 때문에 이번 강좌는 자바에 대해 혹은 개발에 대해 아무것도 모르시는 분들께는 어려울 수 있다는 점, 미리 말씀드립니다.

 

먼저 늘 그래 왔듯이 클래스를 하나 만듭니다.

클래스명은 GachaBoxResult입니다.

 

먼저 List라는 것을 사용할 것입니다.

List를 간단하게 말하자면 자료형을 정하고 많은 자료들을 배열에 비해 편하게 사용을 할 수 있도록 하는 Collection 중 하나입니다.

Collection는 List와 같이 배열보다 편하게 많은 자료들을 사용할 수 있도록 하는 자바의 내장 인터페이스입니다.

계속 얘기를 하자면 길어지기에 인터페이스에 대해서만 얘기하고 다시 본론으로 넘어가겠습니다.

인터페이스는 implements를 사용하여, 해당 인터페이스를 상속(대충 인터페이스라는 것을 사용한다는 의미)하여 

인터페이스를 사용할 수 있습니다.

인터페이스는 편한 유지보수 및 코드 관리에 유용합니다.

한 마디로 요약하자면 귀찮고, 더럽게 중복 코드를 사용하지 않도록 도와주는 것이 인터페이스라고 생각하시면 될 것 같습니다.

 

다시 본론으로 넘어와서

이처럼 복잡하다면 복잡한 이 List를 어디에 사용할 것이냐?

바로 가챠 상자 결과를 산출해낼 때, 모든 것들을 하나로 묶어서 랜덤으로 산출해내기 위해 사용할 것입니다.

 

저는 가챠 상자에 마크 내에 있는 모든 엔티티, 모든 아이템, 그리고 모든 포션 효과를 랜덤 하게 나오게 하고 싶기에

Entity타입, Material타입, 그리고 PotionEffectType타입인 리스트 3개를 만들고

최종으로 이 3가지 중 랜덤으로 하나가 나와야 하므로 Object타입인 리스트를 하나 더 만듭니다.

 

Object타입 리스트는 왜 만드는 가?

자바에 모든 클래스는 Object를 상속이 되어있기에 어떤 클래스든 간에 Object로 묶을 수 있습니다.

 

public static List<EntityType> entities = new ArrayList<>();
public static List<Material> materials = new ArrayList<>();
public static List<PotionEffectType> effects = new ArrayList<>();
public static List<Object> objectList = new ArrayList<>();

위처럼 리스트를 선언해주시고

 

static 블럭이라는 것을 사용할 것입니다.

static은 정적이라는 의미를 가지고 있습니다.

위 코드에도 static이 있습니다.

static에 대해 짧게 말씀드리고 다시 본론으로 가겠습니다.

 

static은 위에 말한 것처럼 정적입니다.

한 마디로, 프로그램이 종료되기 전까지 계속 정적으로 남아있다는 의미입니다.

정적이 아닌 것들은 메소드 종료 등 여러 이유들로 사라지게 되는 데, 정적인 것들은 프로그램 최초 실행했을 때

바로 선언이 됩니다.

그런 static을 아무런 것도 안 적고

그냥 static {}를 사용할 경우, 자바가 실행하면서 동시에 클래스를 확인하면서 바로 실행이 되는 영역입니다.

 

그래서 이런 static 블럭 ({}를 블럭이라고 부릅니다.)를 사용하여 먼저 값을 넣어줍니다.

static {
    entities.addAll(Arrays.stream(EntityType.values()).toList());
    materials.addAll(Arrays.stream(Material.values()).toList());
    effects.addAll(Arrays.asList(PotionEffectType.values()));
    objectList.addAll(materials);
    objectList.addAll(effects);
    objectList.addAll(entities);
}

entities 리스트에 모든 값을 넣을 수 있는 메소드인 addAll로 EntityType에 모든 값들을 Arrays.stream을 사용하여 배열로 바꾸고, 이를 다시 리스트로 바꾸어 같은 Collection으로 바꾸어 모든 값을 넣습니다.

이를 계속하여 결국 모든 값들을 제가 넣고 싶은 데 다 넣을 수 있습니다.

 

그리고 가챠를 실행했을 때

가운데 화면에 빠르게 현재 뭐가 돌아가고 있는지 띄우는 것과 더불어

상자 결과가 정해지면 폭죽을 터뜨리고 싶기 때문에

 

먼저 폭죽을 생성하는 메소드를 작성한 후, 결과 메소드 작성, 그리고 최종적으로 화면 코드 작성하는 순서로 개발하겠습니다.

 

폭죽 생성 메소드는 일단 메소드명은 customFireWork이라고 하였고,

인자 값은 Firework, FireworkMeta, power, FireworkEffect.Type, Color입니다.

public void customFireWork(Firework firework, FireworkMeta meta,
        int power, FireworkEffect.Type type, Color color) {
    meta.setPower(power);
    meta.addEffect(FireworkEffect.builder().with(type).withColor(color).flicker(true).build());

    firework.setFireworkMeta(meta);
}

위처럼 폭죽에게 특별한 이펙트를 추가합니다.

이후 결과 메소드를 작성하여 줍니다.

public void result(Player player, Object item) {
    player.sendTitle("Selected from Gacha box", String.valueOf(item), 10, 70, 20);
    Firework firework = (Firework) player.getWorld().spawnEntity(player.getLocation(), EntityType.FIREWORK);
    FireworkMeta meta = firework.getFireworkMeta();

    if (item instanceof EntityType type) {
        customFireWork(firework, meta, 10, FireworkEffect.Type.CREEPER, Color.BLACK);
        spawnEntity(player, type);
        return;
    }
    if (item instanceof Material material) {
        customFireWork(firework, meta, 10, FireworkEffect.Type.BURST, Color.OLIVE);
        giveItem(player, material);
        return;
    }
    if (item instanceof PotionEffectType effectType) {
        customFireWork(firework, meta, 10, FireworkEffect.Type.STAR, Color.AQUA);
        giveEffect(player, effectType);
    }
}

public void spawnEntity(Player player, EntityType e) {
    player.getWorld().spawnEntity(player.getLocation(), e);
}

public void giveItem(Player player, Material material) {
    ItemStack itemStack = new ItemStack(material);
    player.getInventory().addItem(itemStack);
}

public void giveEffect(Player player, PotionEffectType effectType) {
    player.addPotionEffect(new PotionEffect(effectType, 120, 1, true));
}

위처럼 작성하여 폭죽과 더불어 결과까지 작동하도록 합니다.

 

이제 마지막인 랜덤 결정 코드를 작성한 후, 테스트를 하기 위한 명령어를 짧게 적으면 거의 완성입니다.

생성자를 사용하여 랜덤 결정 코드를 작성합니다.

public GachaBoxResult(Player player, Plugin plugin) {
    Random random = new Random();
    new BukkitRunnable() {
        int count = 0;

        @Override
        public void run() {
            int r = random.nextInt(objectList.size());
            Object o = objectList.get(r);
            String next = String.valueOf(o);

            if (count > 50) {
                result(player, o);
                this.cancel();
            }
            else {
                player.sendTitle("가챠 상자 여는 중", next, 0, 3, 0);
                count++;
            }
        }
    }.runTaskTimer(plugin, 3L, 3L);
}

총 50번 동안 3 틱 (1 틱은 0.05초)마다 바꾸어 50번 동안 돌았다면 루프를 취소하고 result 메소드를 호출하여

결과를 산출한다.

 

이제 테스트를 위한 명령어를 간단하게 만들고 테스트를 하면 끝이다.

command 패키지를 하나 만들고

해당 패키지에 PluginCommand라는 클래스를 만들고

아래와 같이 명령어를 받을 수 있도록 세팅을 합니다.

public class PluginCommand implements CommandExecutor {

    private final Plugin plugin;

    public PluginCommand(Plugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    }
}

이후, 셜커 상자를 지급합니다.

public class PluginCommand implements CommandExecutor {

    private final Plugin plugin;

    public PluginCommand(Plugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (sender instanceof Player player) {
            if (label.equalsIgnoreCase("test")) {
                GachaBox.createGachaBox(player);
            }
        }
    }
}

메인 클래스에서 아래와 같이 작성하여 test라는 이름인 명령어에 대해 작성한 뒤, 

getCommand("test").setExecutor(new CommandManager(this));

 

그리고 plugin.yml에서 아래와 같이 세팅을 하면 드디어 결과물이 나온다.

commands:
  test:
    description: blah
    usage: /test

여기까지 따라오셨다면 거의 끝입니다.

이제 타이머 기능만 추가하면 가챠 플러그인 완성입니다.

 

이상입니다.

'잡다한 개발 > 마크플러그인' 카테고리의 다른 글

마크 가챠 5편  (0) 2021.11.30
마크 가챠 3편  (0) 2021.11.23
마크 가챠 2편  (0) 2021.11.20
마크 가챠 1편  (0) 2021.11.20
마크 가챠 0편  (0) 2021.11.19