Skip to content

Commit

Permalink
2.1 (#5)
Browse files Browse the repository at this point in the history
* Use gradle

* Add permission for interacting with slimes with a bucket

* Update config to use `MiniMessage` format. Extract config vars into `PluginConfig`

* Update `foojay-resolver-convention`

* Code cleanup

* Update NBTAPI and fix its shading

* Update deps. Simplify iterations in `SlimeListener`

* Code cleanup. Naming

* Code cleanup. Update for Minecraft 1.21
  • Loading branch information
DanikVitek authored Sep 27, 2024
1 parent 96a5499 commit 866cf14
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 58 deletions.
16 changes: 8 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
plugins {
`java-library`
id("com.github.johnrengelman.shadow") version "8.1.1"
id("io.papermc.paperweight.userdev") version "1.5.11"
id("xyz.jpenilla.run-paper") version "2.2.2"
alias(libs.plugins.shadow)
alias(libs.plugins.paperweight.userdev)
alias(libs.plugins.runpaper)
}

group = "com.danikvitek"
version = "2.0"
version = "2.1"

repositories {
mavenCentral()
Expand All @@ -30,10 +30,10 @@ repositories {

dependencies {
paperweight.paperDevBundle("1.18.2-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:24.1.0")
implementation("org.bstats:bstats-bukkit:3.0.2")
implementation("de.tr7zw:item-nbt-api:2.12.2")
implementation("io.vavr:vavr:0.10.4")
compileOnly(libs.jetbrains.annotations)
implementation(libs.bstats.bukkit)
implementation(libs.itemnbt.api)
implementation(libs.vavr)
}

java {
Expand Down
101 changes: 58 additions & 43 deletions src/main/java/com/danikvitek/slimeinabukkit/SlimeListener.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.danikvitek.slimeinabukkit;

import com.danikvitek.slimeinabukkit.config.PluginConfig;
import de.tr7zw.changeme.nbtapi.NBTItem;
import com.danikvitek.slimeinabukkit.util.ISUtil;
import de.tr7zw.changeme.nbtapi.NBT;
import io.vavr.collection.Iterator;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Chunk;
import org.bukkit.Location;
Expand All @@ -18,15 +22,11 @@
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand All @@ -41,7 +41,7 @@ public class SlimeListener implements Listener {
public static final String SLIME_INTERACT_PERMISSION = "slimeinabukkit.interact";
public static final Random RANDOM = new Random();

private static final Set<UUID> interactingPlayers = new LinkedHashSet<>();
private static final Set<UUID> interactingPlayers = new HashSet<>();
private static final Map<Item, Chunk> lastItemChunks = new ConcurrentHashMap<>();

private final @NotNull PluginConfig config;
Expand Down Expand Up @@ -167,9 +167,9 @@ private void pickupSlime(final @NotNull Slime slime,

private void assignUUID(final @NotNull ItemStack slimeBucketStack,
final @NotNull UUID uuid) {
final var nbtItem = new NBTItem(slimeBucketStack);
nbtItem.setUUID(SLIME_BUCKET_UUID_KEY, uuid);
nbtItem.applyNBT(slimeBucketStack);
NBT.modify(slimeBucketStack, nbt -> {
nbt.setUUID(SLIME_BUCKET_UUID_KEY, uuid);
});
}

@EventHandler
Expand All @@ -193,9 +193,9 @@ public void onClickAtBlock(final @NotNull PlayerInteractEvent event) {
assert itemMeta != null;
if (!itemMeta.hasCustomModelData() ||
(itemMeta.getCustomModelData() != config.getCalmSlimeCmd() &&
itemMeta.getCustomModelData() != config.getActiveSlimeCmd())) return;
itemMeta.getCustomModelData() != config.getActiveSlimeCmd())) return;

placeSlime(event, player, itemStack, itemMeta);
placeSlime(event, player, itemStack);
}

private boolean checkCannotPickupSlime(@NotNull Player player) {
Expand All @@ -213,30 +213,33 @@ private boolean checkCannotPickupSlime(@NotNull Player player) {

private void placeSlime(final @NotNull PlayerInteractEvent event,
final @NotNull Player player,
final @NotNull ItemStack itemStack,
final @NotNull ItemMeta itemMeta) {
final @NotNull ItemStack itemStack) {
if (!itemStack.hasItemMeta()) throw new AssertionError("ItemStack has no ItemMeta");
final ItemMeta itemMeta = itemStack.getItemMeta();

if (interactingPlayers.contains(player.getUniqueId())) return;
interactingPlayers.add(player.getUniqueId());

event.setUseInteractedBlock(Event.Result.DENY);

final Block block = event.getClickedBlock();
assert block != null;
assert block != null; // because the event.action is RIGHT_CLICK_BLOCK
final BlockFace blockFace = event.getBlockFace();

final Location slimeReleaseLocation = block.getLocation().clone()
.add(new Vector(0.5, 0d, 0.5))
final Location slimeReleaseLocation = block.getLocation()
.add(0.5, 0d, 0.5)
.add(blockFace.getDirection());
slimeReleaseLocation.setYaw(RANDOM.nextFloat() * 360f);

player.getWorld().spawn(slimeReleaseLocation, Slime.class, slime -> {
slime.setSize(1);
final var serializer = PlainTextComponentSerializer.plainText();
if (itemMeta.hasDisplayName() &&
!serializer.serialize(itemMeta.displayName())
.equals(serializer.serialize(config.getSlimeBucketTitle()))) {
slime.customName(itemMeta.displayName());
}
ISUtil.useDisplayName(itemMeta, displayName -> {
if (!serializer.serialize(displayName)
.equals(serializer.serialize(config.getSlimeBucketTitle()))) {
slime.customName(itemMeta.displayName());
}
});
});

itemMeta.setCustomModelData(null);
Expand All @@ -252,27 +255,35 @@ private void placeSlime(final @NotNull PlayerInteractEvent event,
}

private void removeUUID(final @NotNull ItemStack itemStack) {
final var nbtItem = new NBTItem(itemStack);
nbtItem.removeKey(SLIME_BUCKET_UUID_KEY);
nbtItem.applyNBT(itemStack);
NBT.modify(itemStack, nbt -> {
nbt.removeKey(SLIME_BUCKET_UUID_KEY);
});
}

@EventHandler(priority = EventPriority.MONITOR)
public void onCraftWithSlimeBucket(final @NotNull CraftItemEvent e) {
final int matrixSize = e.getInventory().getMatrix().length;
final Map<Integer, ItemStack> slotsAndStacksToReplaceWithSlimeBucket = new LinkedHashMap<>(matrixSize);
io.vavr.collection.Iterator
.of(e.getInventory().getMatrix())
.zipWithIndex()
.filter(pair -> pair._1 != null && pair._1.getType() == SLIME_BUCKET_MATERIAL && pair._1.hasItemMeta())
.filter(pair -> {
final ItemMeta itemMeta = pair._1.getItemMeta();
assert itemMeta != null;
return itemMeta.hasCustomModelData() &&
(itemMeta.getCustomModelData() == config.getCalmSlimeCmd() ||
itemMeta.getCustomModelData() == config.getActiveSlimeCmd());
})
.forEach(pair -> slotsAndStacksToReplaceWithSlimeBucket.put(pair._2, pair._1.clone()));
final Int2ObjectMap<@NotNull ItemStack> slotsAndStacksToReplaceWithSlimeBucket =
new Int2ObjectLinkedOpenHashMap<>(matrixSize);
Iterator.of(e.getInventory().getMatrix())
.zipWithIndex()
.filter(pair -> {
final ItemStack itemStack = pair._1;
if (itemStack == null || itemStack.getType() != SLIME_BUCKET_MATERIAL || !itemStack.hasItemMeta()) {
return false;
}
final ItemMeta itemMeta = itemStack.getItemMeta();
assert itemMeta != null;
return itemMeta.hasCustomModelData() &&
(itemMeta.getCustomModelData() == config.getCalmSlimeCmd() ||
itemMeta.getCustomModelData() == config.getActiveSlimeCmd());
})
.forEach(pair -> {
final ItemStack itemStack = pair._1;
assert itemStack != null;
final int slot = pair._2;
slotsAndStacksToReplaceWithSlimeBucket.put(slot, itemStack.clone());
});

scheduler.runTaskLater(() -> {
final ItemStack[] newMatrix = new ItemStack[matrixSize];
Expand All @@ -287,11 +298,10 @@ public void onCraftWithSlimeBucket(final @NotNull CraftItemEvent e) {
newMatrix[slot] = clonedBucket;
});

io.vavr.collection.Iterator
.of(e.getInventory().getMatrix())
.zipWithIndex()
.filter(pair -> newMatrix[pair._2] == null)
.forEach(pair -> newMatrix[pair._2] = pair._1);
Iterator.of(e.getInventory().getMatrix())
.zipWithIndex()
.filter(pair -> newMatrix[pair._2] == null)
.forEach(pair -> newMatrix[pair._2] = pair._1);
e.getInventory().setMatrix(newMatrix);
}, 0L);
}
Expand Down Expand Up @@ -326,4 +336,9 @@ public void onSlimeBucketDrop(final @NotNull PlayerDropItemEvent event) {
}
}, 0L, 1L);
}

@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(final @NotNull PlayerQuitEvent event) {
interactingPlayers.remove(event.getPlayer().getUniqueId());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.danikvitek.slimeinabukkit.command;

import com.danikvitek.slimeinabukkit.config.PluginConfig;
import de.tr7zw.changeme.nbtapi.NBTItem;
import de.tr7zw.changeme.nbtapi.NBT;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Location;
Expand Down Expand Up @@ -54,13 +54,14 @@ private void getSlimeImpl(@NotNull CommandSender sender) {

slimeBucketMeta.displayName(config.getSlimeBucketTitle());
slimeBucket.setItemMeta(slimeBucketMeta);
final NBTItem nbtItem = new NBTItem(slimeBucket);
nbtItem.setUUID(SLIME_BUCKET_UUID_KEY, UUID.randomUUID()); // for it to be not stackable
nbtItem.applyNBT(slimeBucket);
NBT.modify(slimeBucket, nbt -> {
nbt.setUUID(SLIME_BUCKET_UUID_KEY, UUID.randomUUID()); // for it to be not stackable
});

final World world = player.getWorld();
world.playSound(location, Sound.ENTITY_ITEM_PICKUP, 1f, 1f);
if (!player.getInventory().addItem(slimeBucket).isEmpty())
if (!player.getInventory().addItem(slimeBucket).isEmpty()) {
world.dropItem(player.getEyeLocation(), slimeBucket);
}
}
}
31 changes: 31 additions & 0 deletions src/main/java/com/danikvitek/slimeinabukkit/util/ISUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.danikvitek.slimeinabukkit.util;

import net.kyori.adventure.text.Component;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;

import java.util.function.Consumer;

/**
* Utility class for {@link org.bukkit.inventory.ItemStack}.
*/
public final class ISUtil {
private ISUtil() {
}

public static void useDisplayName(final @NotNull ItemStack itemStack, final @NotNull Consumer<@NotNull Component> consumer) {
if (!itemStack.hasItemMeta()) {
final ItemMeta itemMeta = itemStack.getItemMeta();
useDisplayName(itemMeta, consumer);
}
}

public static void useDisplayName(final @NotNull ItemMeta itemMeta, final @NotNull Consumer<@NotNull Component> consumer) {
if (itemMeta.hasDisplayName()) {
final Component displayName = itemMeta.displayName();
assert displayName != null;
consumer.accept(displayName);
}
}
}
4 changes: 2 additions & 2 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ permissions:
commands:
get_slime:
permission: "slimeinabukkit.command.get_slime"
usage: "/get_slime | /gs"
usage: "/get_slime"
description: "Gives a bucket of slime to the player"
slime_chunk:
permission: "slimeinabukkit.command.slime_chunk"
usage: "/slime_chunk | /sc"
usage: "/slime_chunk"
description: "Tells you, if the chunk you are in is a slime chunk"

0 comments on commit 866cf14

Please sign in to comment.