예전에 마인크래프트를 하며 목검의 데미지를 20으로 변경시키는 작업을 해보겠다고 이야기 했었는데요.
커맨드를 통해 데미지가 20인 커스텀 목검을 제작해보도록 하겠습니다.
이번에도 플러그인을 만들기 전에 설계를 먼저 해보도록 하겠습니다.
"/목검" 이라는 커맨드를 입력하면
유저에게 데미지 20의 목검을 전달하는
플러그인을 개발할 예정입니다.
우선 Maven 을 통해 기본적인 프로젝트를 구성해보도록 하겠습니다.
7. 마인크래프트 플러그인 개발 - 데미지 디스플레이 플러그인 개발 — 느리게 올라가는 달팽이 (tistory.com)
7. 마인크래프트 플러그인 개발 - 데미지 디스플레이 플러그인 개발
이번에도 Listener 와 조금 더 친해지기 위해 플러그인 개발을 실습해보도록 하겠습니다. 2편 에서 서버와의 통신에 대해 이야기할 때 플레이어가 검으로 좀비를 공격했을 때 체력을 알 수 있는
beingb.tistory.com
7 장에서 이야기 한 것과 같이 pom.xml 파일의 디펜던시를 수정하는 것이 아닌
build Path 에 spgiot API 를 추가하는 형식으로 제작했습니다.
name : CustomWeaponPlugin
main : com.tistory.beingb.main.CustomWeaponPlugin
version : 0.0.1
api-version : 1.21.1
commands :
무기 :
description : 데미지 20의 나무검을 주는 명령어 입니다.
usage : /무기
Commands 는 위에서 이야기 한 것과 같이 무기 로 하기 위해 plugin.yml 파일을 수정합니다.
이번엔 작업할 때 api-version 이라는 Key 와 Value 값이 추가됐는데요.
내가 개발하고 있는 spigot 의 API version 을 명시해주지 않으면, No legacy enum constant for 이라는 에러가 발생합니다.
이 에러를 추론해 보자면, spigot 서버는 내가 어떤 버전의 API 를 사용하고 있는지 알려주지 않으면, 구형 버전의 API 를 사용하고 있을 것이라 추측할 수 있습니다.
만약 구형 버전의 API 를 사용한다면 마인크래프트의 아이템 중에 현재의 버전의 아이템이 아닌 legacy 아이템을 사용해야 할 수도 있습니다.
그래서 spigot 은 유저에게 이 아이템은 legacy 아이템이 아니기에 만약 너가 legacy 아이템을 사용하지 않을 거라면 api-version 이 최신 버전이라는 것을 알려달라는 오류 문구라 추측할 수 있습니다.
현재 1.21.1 버전의 spigot API 를 사용하고 있기 때문에 api-version 의 value 는 1.21.1 로 둡니다.
내가 만들고 싶은 명령어는 "/무기" 라는 명령어 입니다.
그 외의 것들은 무시할 수 있도록 해야하는데요.
Early return 을 활용해 이름이 무기가 아닌 경우와 "/무기" 뒤에 이상한 인자가 붙는 것을 방지하기 위해
해당 케이스에는 false 를 리턴해 usage 를 노출하도록 합니다.
이제는 커스텀 아이템을 제작해야 하는 차례인데요.
구글에 spigot custom item 으로 검색해보도록 하겠습니다.
java - How do you create a custom item in Spigot 1.16.5? - Stack Overflow
How do you create a custom item in Spigot 1.16.5?
I'm making a plugin that adds some useful items like House Building Wand, Exploding Sword, etc. But how can I add those items using the plugin?
stackoverflow.com
위의 글에 커스텀 아이템을 어떻게 만드는지 간략한 방법이 나와있는데요.
ItemStack 이라는 타입과 Material 이라는 Enum Class 를 활용해 아이템을 제작할 수 있는 것 같습니다.
ItemStack (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
ItemStack (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Cloneable, ConfigurationSerializable, Translatable Represents a stack of items. IMPORTANT: An ItemStack is only designed to contain items. Do not use this class to encapsulate Materials for which Material.isItem() returns false.
hub.spigotmc.org
이렇게 기본이되는 나무검을 제작할 수 있는 것 같습니다.
이제 나무 검의 무기 데미지를 변경해야 하는데요.
google 에 spigot weapon damage change 라고 검색해보면
item 의 meta 에 attributeModifier 라는 것을 교체하는 방법을 통해 무기의 데미지를 변경할 수 있다는 것 같습니다.
조금 더 리서칭을 해본 결과
위와 같은 방법으로 무기의 데미지나 무기의 공격 속도를 변경할 수 있다는 것 같습니다.
AttributeModifier (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
AttributeModifier (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: ConfigurationSerializable, Keyed Concrete implementation of an attribute modifier. Nested Class Summary Nested Classes Constructor Summary Constructors Method Summary Constructor Details AttributeModifier Deprecated. AttributeMo
hub.spigotmc.org
그래서 AttributeModifier 를 검색해 봤는데
대부분의 생성자들이 Deprecated 됐고, 마지막 NamespacedKey 를 활용하는 생성자만 남아있습니다.
NamespacedKey (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
NamespacedKey (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
public final class NamespacedKey extends Object Represents a String based key which consists of two components - a namespace and a key. Namespaces may only contain lowercase alphanumeric characters, periods, underscores, and hyphens. Keys may only contain
hub.spigotmc.org
해당 AttributeModifier 를 만들기 위해서는 다른 AttributeModifier 과 구분하기 위해 첫 번째 인자로 UUID 를 사용해줬던 것 같습니다.
헌데, 하나의 서버에는 여러 플러그인이 부착될 수 있고 UUID 는 겹칠 가능성이 있다고 판단했던 것 같습니다.
그래서 플러그인 안에서 구분자로 고유한 Key 를 만들기 위해 NamespacedKey 라는 것을 활용하는 것으로 변경된 것 같습니다.
NamespacedKey 의 생성자로는 내가 개발 중인 plugin 과 key 가 들어가게 되는데요.
Command 클래스의 생성자를 통해 main Class 를 가져와서
attackDamageModifierKey 라는 NamespacedKey 타입의 변수를 제작합니다.
그 다음은 AttributeModifier 를 제작해야 하는데요. 첫 번째로는 위에서 제작했던 NamespacedKey 를 넣고
두 번째는 추가할 데미지입니다. 19.0 을 준 이유는 base Value 가 1이기에, 19를 더하여 20을 만들기 위함입니다.
AttributeModifier.Operation 은 ADD_NUMBER 라는 것으로 기본 데미지에 더해주는 Attribute 로 제작합니다.
마지막 장착 슬롯은 MAIN HAND 에 가지고 있을 때 작동할 옵션이기 때문에, EquipmentSlotGoup.MAINHAND 값을 추가합니다.
AttributeModifier.Operation (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
AttributeModifier.Operation (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Serializable, Comparable , Constable Enclosing class: AttributeModifier Enumerable operation to be applied. Nested Class Summary Enum Constant Summary Enum Constants Adds (or subtracts) the specified amount to the base value. Ad
hub.spigotmc.org
EquipmentSlotGroup (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
EquipmentSlotGroup (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Predicate Field Summary Fields Method Summary Copyright © 2024. All rights reserved.
hub.spigotmc.org
그 다음은 제작한 AttributeModifier 를 ItemMeta 에 추가해줍니다.
ItemMeta (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
ItemMeta (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Superinterfaces: Cloneable, ConfigurationSerializable, PersistentDataHolder All Known Subinterfaces: ArmorMeta, AxolotlBucketMeta, BannerMeta, BlockDataMeta, BlockStateMeta, BookMeta, BundleMeta, ColorableArmorMeta, CompassMeta, CrossbowMeta, Damageabl
hub.spigotmc.org
ItemMeta 에 attributeModifier 를 추가하기 위해서는 addAttributeModifier 라는 메서드를 활용해야 하는데요.
첫 번재 인자로는 추가하고 싶은 Attribute Enum Class 를 받습니다.
Attribute (Spigot-API 1.21.1-R0.1-SNAPSHOT API) (spigotmc.org)
Attribute (Spigot-API 1.21.1-R0.1-SNAPSHOT API)
All Implemented Interfaces: Serializable, Comparable , Constable, Keyed, Translatable Types of attributes which may be present on an Attributable. Nested Class Summary Enum Constant Summary Enum Constants Method Summary All MethodsStatic MethodsInstance Me
hub.spigotmc.org
제가 추가하고 싶은 내용은 ATTACK_DAMAGE 이기 때문에, GENERIC_ATTACK_DAMAGE 에
만든 attackDamageModifier 를 적용시킵니다.
그리고 마지막으로 플레이어에게 아이템을 지급하기 위해 addItem 이라는 메서드를 활용해 아이템을 추가해줍니다.
package com.tistory.beingb.command;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlotGroup;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import com.tistory.beingb.main.CustomWeaponPlugin;
public class CustomWeaponPluginCommand implements CommandExecutor {
CustomWeaponPlugin customWeaponPlugin;
public CustomWeaponPluginCommand(CustomWeaponPlugin customWeaponPlugin) {
// TODO Auto-generated constructor stub
this.customWeaponPlugin = customWeaponPlugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) {
if (!command.getName().equals("무기"))
return false;
if (!(args.length == 0))
return false;
ItemStack woodenSword = new ItemStack(Material.WOODEN_SWORD);
NamespacedKey attackDamageModifierKey = new NamespacedKey(customWeaponPlugin, "generic.attack.damage");
AttributeModifier attackDamageModifier = new AttributeModifier(attackDamageModifierKey, 19.0,
AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.MAINHAND);
ItemMeta woodenSwordItemMeta = woodenSword.getItemMeta();
woodenSwordItemMeta.addAttributeModifier(Attribute.GENERIC_ATTACK_DAMAGE, attackDamageModifier);
woodenSword.setItemMeta(woodenSwordItemMeta);
Player player = (Player) sender;
player.getInventory().addItem(woodenSword);
return true;
}
}
만든 커맨드를 main Class 에 등록해주도록 하겠습니다.
package com.tistory.beingb.main;
import org.bukkit.plugin.java.JavaPlugin;
import com.tistory.beingb.command.CustomWeaponPluginCommand;
public class CustomWeaponPlugin extends JavaPlugin {
@Override
public void onDisable() {
// TODO Auto-generated method stub
super.onDisable();
}
@Override
public void onEnable() {
// TODO Auto-generated method stub
super.onEnable();
this.getCommand("무기").setExecutor(new CustomWeaponPluginCommand(this));
}
@Override
public void onLoad() {
// TODO Auto-generated method stub
super.onLoad();
}
}
이제 플러그인을 제작해 서버에 적용시켜보도록 하겠습니다.
플러그인 적용 시 자동 완성 기능이 뜨는것을 통해 명령어가 정상적으로 등록되어 있는 것을 확인할 수 있고 명령어를 입력 시
Attack Damage 가 +19 된 나무 검을 지급받은 것을 확인할 수 있습니다.
무기의 설명란에 When in Main Hand 가 있는 것을 통해
Attribute Modifier 를 제작할 때 마지막 인자로 MAIN HAND 를 준 내용이 여기에 적용된 것을 확인할 수 있습니다.
그러면 7장 에서 데미지 디스플레이 플러그인을 개발했으니 데미지가 20이 된 것인지 확인해보도록 하겠습니다.
나무검의 데미지가 20이 되고 좀비를 공격했을 때 20의 데미지가 들어가서 남은 체력이 0이 된 것을 확인할 수 있습니다.
이번 플러그인을 개발하며 좀비의 체력이 0일 때 죽는 것이 아닌, 음수 값이 되어야 사망으로 판정한다는 것을 알 수 있었습니다.
'마인크래프트' 카테고리의 다른 글
12. 마인크래프트 플러그인 개발 - 더블 점프 플러그인 개발 (1) | 2024.11.01 |
---|---|
10. 마인크래프트 플러그인 개발 - 작물 성장 체크 플러그인 개발 (0) | 2024.08.25 |
9. 마인크래프트 플러그인 개발 - 챗컬러 플러그인 개발 (0) | 2024.08.24 |
7. 마인크래프트 플러그인 개발 - 데미지 디스플레이 플러그인 개발 (0) | 2024.08.16 |
6. 마인크래프트 플러그인 개발 - Listener 활용 (0) | 2024.08.16 |