저장 데이터와 명령어
수확할 때마다 두 곳에 기록을 남깁니다.
| 기록 | API | 저장 위치 | 클라이언트로 |
|---|---|---|---|
| 플레이어가 얻은 크리스털 수 | 엔티티 데이터 | 플레이어 저장 데이터. 리스폰해도 유지됨 | 그 플레이어 자신에게 |
| 이 월드의 수확 횟수 | 월드 저장소 | 월드 폴더 | 모든 플레이어에게 |
선언
CrystalGardenMod에 저장소 ID, 옵션, 엔티티 데이터 키를 추가합니다.
CrystalGardenMod.java
/** Garden totals of the world, copied to every client so the HUD can show them. */
static final ResourceId GARDEN_STATS = ResourceId.of(MOD_ID, "garden_stats");
static final StorageOptions GARDEN_STATS_OPTIONS = StorageOptions.DEFAULT.syncedToClients();
/** Crystals each player harvested; saved with the player and sent to that player's client. */
static EntityDataKey harvested;
onInitializeCommon 안에서 키를 만듭니다. true는 해당 플레이어 자신의 클라이언트로 데이터를 보낸다는 뜻입니다.
CrystalGardenMod.java (onInitializeCommon)
harvested = mod.content().entityData("harvested", true);
수확 기록
자라는 블록에서 임시로 만든 harvest를 다음 코드로 바꿉니다.
CrystalSprout.java
/** Gives the crystals of a ripe sprout to {@code player} and records the harvest. */
static void harvest(WorldView world, BlockPos pos, PlayerView player) {
world.setProperty(pos, STAGE, 0);
player.give(CrystalGardenMod.CRYSTAL, CRYSTALS_PER_HARVEST);
StoredData mine = player.data(CrystalGardenMod.harvested);
mine.data().putInt("count", mine.data().getInt("count", 0) + CRYSTALS_PER_HARVEST);
mine.markChanged();
StoredData stats = world.storage(CrystalGardenMod.GARDEN_STATS, CrystalGardenMod.GARDEN_STATS_OPTIONS);
stats.data().putInt("harvests", stats.data().getInt("harvests", 0) + 1);
stats.markChanged();
world.playSound(pos, ResourceId.minecraft("block.amethyst_block.chime"), 1.0f, 1.2f);
world.spawnParticles(
ResourceId.minecraft("happy_villager"), pos.x() + 0.5, pos.y() + 0.6, pos.z() + 0.5, 8, 0.3);
}
data()는 정수, 문자열, 하위 트리 등을 담는DataTree입니다. 값을 바꾼 뒤markChanged()를 호출해야 저장되고 클라이언트로도 전달됩니다.- 같은 저장소 ID는 어디서 열든 같은 옵션으로 열어야 하며, 다르면
IllegalArgumentException이 발생합니다. 그래서 옵션을 상수 하나로 둡니다. - 소리와 파티클에는 바닐라 ID를 그대로 사용합니다.
명령어와 권한
새 파일 GardenCommands.java를 만듭니다. /garden stats는 누구나 사용할 수 있고, /garden grow <위치>는 권한이 있는 사람만 사용할 수 있습니다.
src/main/java/com/example/crystalgarden/GardenCommands.java
final class GardenCommands {
private GardenCommands() {}
static void register(CommandRegistrar commands) {
commands.register(CommandNode.literal("garden")
.then(CommandNode.literal("stats").executes(context -> {
StoredData stats = context.source()
.world()
.storage(CrystalGardenMod.GARDEN_STATS, CrystalGardenMod.GARDEN_STATS_OPTIONS);
int harvests = stats.data().getInt("harvests", 0);
String mine = context.source()
.player()
.map(player -> ", you harvested "
+ player.data(CrystalGardenMod.harvested)
.data()
.getInt("count", 0)
+ " crystal(s)")
.orElse("");
context.source().sendMessage("Crystal Garden: " + harvests + " harvest(s) in this world" + mine);
return harvests;
}))
.then(CommandNode.literal("grow")
.requiresPermission(CrystalGardenMod.growPermission)
.then(CommandNode.argument("pos", CommandArgumentType.blockPos())
.executes(context -> {
if (!CrystalSprout.ripen(context.source().world(), context.getBlockPos("pos"))) {
context.source().sendFailure("There is no crystal sprout there");
return 0;
}
context.source().sendMessage("The crystal sprout is ripe");
return 1;
}))));
}
}
ripen은 CrystalSprout에 둡니다.
CrystalSprout.java
/** Ripens the sprout at {@code pos} at once; false when there is no sprout. */
static boolean ripen(WorldView world, BlockPos pos) {
if (!world.blockAt(pos).equals(CrystalGardenMod.CRYSTAL_SPROUT)) {
return false;
}
return world.setProperty(pos, STAGE, RIPE);
}
엔트리포인트에서 권한 노드를 만들고 명령어를 등록합니다. 권한 노드를 명령어보다 먼저 만들어야 합니다.
CrystalGardenMod.java
/** Who may ripen sprouts with {@code /garden grow}: operators (level 2) unless a permission mod says otherwise. */
static PermissionNode growPermission;
// onInitializeCommon 안
growPermission = mod.permissions().node("grow", 2);
GardenCommands.register(mod.commands());
- 노드 ID는
crystal_garden:grow입니다. 기본값은 운영자 레벨 2이며, 권한 공급자(권한 관리 모드)는 플레이어마다 허용 여부를 따로 정할 수 있습니다. - 명령어 실행 함수가 반환하는 정수는 명령 블록과
/execute store가 읽어 가는 결과값입니다.
확인
게임에서 새싹을 하나 설치하고 /garden grow <x> <y> <z>(새싹 좌표이며, F3 화면의 바라보는 블록 좌표를 쓰면 됩니다)로 바로 키운 뒤 수확합니다. 그러면 /garden stats가 Crystal Garden: 1 harvest(s) in this world, you harvested 3 crystal(s)라고 알려 줍니다. 월드를 닫았다가 다시 열어도 숫자는 그대로 남아 있습니다.
명령어 인수의 종류와 권한 공급자는 명령어와 권한에서, 저장 데이터의 버전 변환은 저장 데이터와 버전에서 설명합니다.
다음 단계
접속 확인을 추가합니다.