From 01effe18b19eaac9b134743d2b7ac1b79fc3233d Mon Sep 17 00:00:00 2001 From: TomTom <93038247+AverageGithub@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:09:44 +0200 Subject: [PATCH] More datahandler work --- .../axminions/AxMinionsPlugin.java | 2 + .../axminions/command/AxMinionsCommand.java | 16 +++- .../axminions/database/DataHandler.java | 34 +++----- .../axminions/database/Tables.java | 2 +- .../listeners/MinionPlaceListener.java | 78 +++++++++++++++++++ .../axminions/minions/Minion.java | 17 ++++ .../axminions/minions/MinionData.java | 22 ++++-- .../axminions/minions/MinionType.java | 2 + .../axminions/utils/Direction.java | 18 +++++ 9 files changed, 157 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/artillexstudios/axminions/utils/Direction.java diff --git a/src/main/java/com/artillexstudios/axminions/AxMinionsPlugin.java b/src/main/java/com/artillexstudios/axminions/AxMinionsPlugin.java index 3fb7e4e..5106d5b 100644 --- a/src/main/java/com/artillexstudios/axminions/AxMinionsPlugin.java +++ b/src/main/java/com/artillexstudios/axminions/AxMinionsPlugin.java @@ -12,6 +12,7 @@ import com.artillexstudios.axminions.database.DataHandler; import com.artillexstudios.axminions.database.DatabaseConnector; import com.artillexstudios.axminions.listeners.BlockPlaceListener; import com.artillexstudios.axminions.listeners.ChunkListener; +import com.artillexstudios.axminions.listeners.MinionPlaceListener; import com.artillexstudios.axminions.listeners.PlayerListener; import com.artillexstudios.axminions.listeners.WorldListener; import com.artillexstudios.axminions.minions.MinionTicker; @@ -64,6 +65,7 @@ public final class AxMinionsPlugin extends AxPlugin { Bukkit.getPluginManager().registerEvents(new ChunkListener(), this); Bukkit.getPluginManager().registerEvents(new PlayerListener(), this); Bukkit.getPluginManager().registerEvents(new BlockPlaceListener(), this); + Bukkit.getPluginManager().registerEvents(new MinionPlaceListener(), this); if (PaperUtils.isFolia()) { ticker = new FoliaMinionTicker(); diff --git a/src/main/java/com/artillexstudios/axminions/command/AxMinionsCommand.java b/src/main/java/com/artillexstudios/axminions/command/AxMinionsCommand.java index fd8ac9a..feb5962 100644 --- a/src/main/java/com/artillexstudios/axminions/command/AxMinionsCommand.java +++ b/src/main/java/com/artillexstudios/axminions/command/AxMinionsCommand.java @@ -1,5 +1,6 @@ package com.artillexstudios.axminions.command; +import com.artillexstudios.axapi.utils.ContainerUtils; import com.artillexstudios.axapi.utils.MessageUtils; import com.artillexstudios.axminions.AxMinionsPlugin; import com.artillexstudios.axminions.command.arguments.MinionLevelArgument; @@ -14,6 +15,7 @@ import com.artillexstudios.axminions.minions.MinionArea; import com.artillexstudios.axminions.minions.MinionData; import com.artillexstudios.axminions.minions.MinionType; import com.artillexstudios.axminions.minions.MinionWorldCache; +import com.artillexstudios.axminions.utils.Direction; import com.artillexstudios.axminions.utils.FileUtils; import com.artillexstudios.axminions.utils.LocationUtils; import dev.jorel.commandapi.CommandTree; @@ -44,7 +46,13 @@ public final class AxMinionsCommand { .then(MinionTypeArgument.minionType("miniontype") .then(MinionLevelArgument.level("level") .then(new IntegerArgument("amount") - + .executes((sender, args) -> { + Player player = args.getByClass("player", Player.class); + MinionType type = args.getByClass("miniontype", MinionType.class); + Level level = args.getByClass("level", Level.class); + Integer amount = args.getByClass("amount", Integer.class); + handleGive(sender, player, type, level, amount); + }) ) ) ) @@ -102,7 +110,7 @@ public final class AxMinionsCommand { MinionType type = args.getByClass("miniontype", MinionType.class); Level level = args.getByClass("level", Level.class); Location location = LocationUtils.toBlockCenter(sender.getLocation()); - MinionData data = new MinionData(0, type, null, level, new ItemStack(Material.DIAMOND_PICKAXE), null, new HashMap<>()); + MinionData data = new MinionData(0, type, Direction.NORTH, null, level, 0, new ItemStack(Material.DIAMOND_PICKAXE), null, new HashMap<>()); Minion minion = new Minion(location, data); minion.spawn(); MinionArea area = MinionWorldCache.getArea(location.getWorld()); @@ -117,6 +125,8 @@ public final class AxMinionsCommand { } private static void handleGive(CommandSender sender, Player player, MinionType type, Level level, Integer amount) { - + ItemStack item = type.item(new MinionData(0, type, null, null, level, 0, null, null, new HashMap<>(0))); + item.setAmount(amount); + ContainerUtils.INSTANCE.addOrDrop(player.getInventory(), List.of(item), player.getLocation()); } } diff --git a/src/main/java/com/artillexstudios/axminions/database/DataHandler.java b/src/main/java/com/artillexstudios/axminions/database/DataHandler.java index 090c59f..9c14d92 100644 --- a/src/main/java/com/artillexstudios/axminions/database/DataHandler.java +++ b/src/main/java/com/artillexstudios/axminions/database/DataHandler.java @@ -1,8 +1,10 @@ package com.artillexstudios.axminions.database; +import com.artillexstudios.axapi.items.WrappedItemStack; import com.artillexstudios.axapi.nms.NMSHandlers; import com.artillexstudios.axminions.config.Config; import com.artillexstudios.axminions.minions.Minion; +import com.artillexstudios.axminions.minions.MinionData; import com.artillexstudios.axminions.minions.MinionType; import com.artillexstudios.axminions.utils.LogUtils; import com.google.common.base.Preconditions; @@ -13,13 +15,11 @@ import org.jetbrains.annotations.NotNull; import org.jooq.Record; import org.jooq.Record1; import org.jooq.Result; -import org.jooq.impl.DSL; import org.jooq.impl.SQLDataType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; -import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutorService; @@ -97,7 +97,7 @@ public final class DataHandler { futures.add(locations.toCompletableFuture()); - CompletionStage minions = DatabaseConnector.getInstance().context().createTableIfNotExists(Tables.LOCATIONS) + CompletionStage minions = DatabaseConnector.getInstance().context().createTableIfNotExists(Tables.MINIONS) .column(Fields.ID, SQLDataType.INTEGER.identity(true)) .column(Fields.LOCATION_ID, SQLDataType.INTEGER) .column(Fields.OWNER_ID, SQLDataType.INTEGER) @@ -160,7 +160,7 @@ public final class DataHandler { } Record1 insert = DatabaseConnector.getInstance().context() - .insertInto(Tables.TYPES) + .insertInto(Tables.WORLDS) .set(Fields.WORLD_UUID, world.getUID()) .returningResult(Fields.ID) .fetchOne(); @@ -172,22 +172,6 @@ public final class DataHandler { return insert.get(Fields.ID); } - public static int ownerId(Player player) { - Result select = DatabaseConnector.getInstance().context() - .select() - .from(Tables.USERS) - .where(Fields.UUID.eq(player.getUniqueId())) - .fetch(); - - if (!select.isEmpty()) { - Record record = select.get(0); - LogUtils.debug("World select record: {}", record); - return (Integer) record.get("ID"); - } - - return FAILED_QUERY; - } - public static int locationId(int world, Location location) { Result select = DatabaseConnector.getInstance().context() .select() @@ -205,7 +189,7 @@ public final class DataHandler { } Record1 insert = DatabaseConnector.getInstance().context() - .insertInto(Tables.TYPES) + .insertInto(Tables.LOCATIONS) .set(Fields.WORLD_ID, world) .set(Fields.LOCATION_X, location.getBlockX()) .set(Fields.LOCATION_Y, location.getBlockY()) @@ -242,7 +226,13 @@ public final class DataHandler { DatabaseConnector.getInstance().context() .insertInto(Tables.MINIONS) .set(Fields.LOCATION_ID, locationId) - .set(Fields.OWNER_ID, locationId) + .set(Fields.OWNER_ID, minion.ownerId()) + .set(Fields.TYPE_ID, minion.type().id()) + .set(Fields.LEVEL, minion.level().id()) + .set(Fields.CHARGE, minion.charge()) + .set(Fields.FACING, minion.facing().ordinal()) + .set(Fields.TOOL, minion.tool() == null || minion.tool().getType().isAir() ? null : WrappedItemStack.wrap(minion.tool()).serialize()) + .set(Fields.EXTRA_DATA, MinionData.serialize(minion.extraData())) .execute(); }, databaseExecutor).exceptionallyAsync(throwable -> { log.error("An unexpected error occurred while inserting minion!", throwable); diff --git a/src/main/java/com/artillexstudios/axminions/database/Tables.java b/src/main/java/com/artillexstudios/axminions/database/Tables.java index 96d747c..7b9386b 100644 --- a/src/main/java/com/artillexstudios/axminions/database/Tables.java +++ b/src/main/java/com/artillexstudios/axminions/database/Tables.java @@ -7,7 +7,7 @@ import org.jooq.impl.DSL; public final class Tables { public static final Table USERS = DSL.table("axminions_users"); public static final Table TYPES = DSL.table("axminions_types"); - public static final Table WORLDS = DSL.table("axminions_locations"); + public static final Table WORLDS = DSL.table("axminions_worlds"); public static final Table LOCATIONS = DSL.table("axminions_locations"); public static final Table MINIONS = DSL.table("axminions_minions"); } diff --git a/src/main/java/com/artillexstudios/axminions/listeners/MinionPlaceListener.java b/src/main/java/com/artillexstudios/axminions/listeners/MinionPlaceListener.java index ca931a3..d0e135c 100644 --- a/src/main/java/com/artillexstudios/axminions/listeners/MinionPlaceListener.java +++ b/src/main/java/com/artillexstudios/axminions/listeners/MinionPlaceListener.java @@ -1,13 +1,91 @@ package com.artillexstudios.axminions.listeners; +import com.artillexstudios.axapi.items.WrappedItemStack; +import com.artillexstudios.axapi.items.component.DataComponents; +import com.artillexstudios.axapi.items.nbt.CompoundTag; +import com.artillexstudios.axminions.config.Minions; +import com.artillexstudios.axminions.database.DataHandler; +import com.artillexstudios.axminions.minions.Level; +import com.artillexstudios.axminions.minions.Minion; +import com.artillexstudios.axminions.minions.MinionArea; +import com.artillexstudios.axminions.minions.MinionData; +import com.artillexstudios.axminions.minions.MinionType; +import com.artillexstudios.axminions.minions.MinionTypes; +import com.artillexstudios.axminions.minions.MinionWorldCache; +import com.artillexstudios.axminions.utils.Direction; +import com.artillexstudios.axminions.utils.LogUtils; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; public final class MinionPlaceListener implements Listener { @EventHandler public void onPlayerInteractEvent(PlayerInteractEvent event) { + LogUtils.debug("MinionPlaceListener - PlayerInteractEvent"); + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { + LogUtils.debug("Not right click block, but {}.", event.getAction()); + return; + } + Block clickedBlock = event.getClickedBlock(); + if (clickedBlock == null) { + LogUtils.debug("Clicked block is null."); + return; + } + + EquipmentSlot hand = event.getHand(); + if (hand == null) { + LogUtils.debug("Hand is null!"); + return; + } + + ItemStack itemStack = event.getPlayer().getInventory().getItem(hand); + if (itemStack == null || itemStack.getType().isAir()) { + LogUtils.debug("Item is either null, or air!"); + return; + } + + WrappedItemStack wrappedItemStack = WrappedItemStack.wrap(itemStack); + CompoundTag compoundTag = wrappedItemStack.get(DataComponents.customData()); + if (!compoundTag.contains("axminions_minion_type")) { + LogUtils.debug("Does not contain miniontype"); + return; + } + + String typeName = compoundTag.getString("axminions_minion_type"); + if (typeName == null || typeName.isBlank()) { + LogUtils.warn("ItemStack in {}'s hand is an invalid minion; the miniontype is empty!", event.getPlayer().getName()); + return; + } + + MinionType minionType = MinionTypes.parse(typeName); + if (minionType == null) { + LogUtils.warn("ItemStack in {}'s hand is an invalid minion; no miniontype with id {} is loaded!", typeName); + return; + } + + // TODO: level + itemStack.setAmount(itemStack.getAmount() - 1); + Location location = clickedBlock.getRelative(event.getBlockFace()).getLocation(); + // TODO: Database queries, etc.. + // TODO: ownerId + MinionData data = new MinionData(0, minionType, Direction.NORTH, null, minionType.level(1), 0, null, null, new HashMap<>()); + Minion minion = new Minion(location, data); + MinionArea area = MinionWorldCache.getArea(location.getWorld()); + MinionWorldCache.add(minion); + DataHandler.insertMinion(minion).thenRun(() -> { + LogUtils.debug("Inserted minion!"); + }); + minion.spawn(); + area.startTicking(location.getChunk()); } } diff --git a/src/main/java/com/artillexstudios/axminions/minions/Minion.java b/src/main/java/com/artillexstudios/axminions/minions/Minion.java index 4a4221c..0af10b8 100644 --- a/src/main/java/com/artillexstudios/axminions/minions/Minion.java +++ b/src/main/java/com/artillexstudios/axminions/minions/Minion.java @@ -9,6 +9,7 @@ import com.artillexstudios.axapi.utils.EquipmentSlot; import com.artillexstudios.axminions.config.Config; import com.artillexstudios.axminions.integrations.Integrations; import com.artillexstudios.axminions.minions.skins.Skin; +import com.artillexstudios.axminions.utils.Direction; import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; @@ -83,6 +84,22 @@ public final class Minion { } } + public Map extraData() { + return this.minionData.extraData(); + } + + public Direction facing() { + return this.minionData.direction(); + } + + public long charge() { + return this.minionData.charge(); + } + + public int ownerId() { + return this.minionData.ownerId(); + } + public ItemStack tool() { return this.minionData.tool(); } diff --git a/src/main/java/com/artillexstudios/axminions/minions/MinionData.java b/src/main/java/com/artillexstudios/axminions/minions/MinionData.java index e6999da..1f7aa8e 100644 --- a/src/main/java/com/artillexstudios/axminions/minions/MinionData.java +++ b/src/main/java/com/artillexstudios/axminions/minions/MinionData.java @@ -2,6 +2,7 @@ package com.artillexstudios.axminions.minions; import com.artillexstudios.axminions.minions.skins.Skin; import com.artillexstudios.axminions.utils.CollectionUtils; +import com.artillexstudios.axminions.utils.Direction; import org.bukkit.Location; import org.bukkit.inventory.ItemStack; @@ -10,15 +11,16 @@ import java.util.Map; import java.util.regex.Pattern; // The data needed to spawn a minion -public record MinionData(int ownerId, MinionType type, Location linkedChest, Level level, ItemStack tool, Skin skin, HashMap storage) { +public record MinionData(int ownerId, MinionType type, Direction direction, Location linkedChest, Level level, + long charge, ItemStack tool, Skin skin, HashMap extraData) { private static final Pattern SEMICOLON = Pattern.compile(";"); private static final Pattern DASH = Pattern.compile("-"); - public MinionData withSkin(Skin skin) { - return new MinionData(this.ownerId, this.type, this.linkedChest, this.level, this.tool, skin, this.storage); - } - public static String serialize(Map map) { + if (map.isEmpty()) { + return ""; + } + StringBuilder builder = new StringBuilder(); for (Map.Entry entry : map.entrySet()) { builder.append(entry.getKey()).append('-').append(entry.getValue()).append(';'); @@ -28,9 +30,9 @@ public record MinionData(int ownerId, MinionType type, Location linkedChest, Lev return builder.toString(); } - public static Map deserialize(String string) { - if (string.isBlank() || !string.contains("-")) { - return Map.of(); + public static HashMap deserialize(String string) { + if (string.isEmpty()) { + return new HashMap<>(0); } String[] split = SEMICOLON.split(string); @@ -43,4 +45,8 @@ public record MinionData(int ownerId, MinionType type, Location linkedChest, Lev return map; } + + public MinionData withSkin(Skin skin) { + return new MinionData(this.ownerId, this.type, this.direction, this.linkedChest, this.level, this.charge, this.tool, skin, this.extraData); + } } diff --git a/src/main/java/com/artillexstudios/axminions/minions/MinionType.java b/src/main/java/com/artillexstudios/axminions/minions/MinionType.java index e55fe7f..6a4a085 100644 --- a/src/main/java/com/artillexstudios/axminions/minions/MinionType.java +++ b/src/main/java/com/artillexstudios/axminions/minions/MinionType.java @@ -93,6 +93,8 @@ public final class MinionType { CompoundTag tag = wrappedItemStack.get(DataComponents.customData()); // TODO: Store statistics, level, etc tag.putString("axminions_minion_type", this.name); + wrappedItemStack.set(DataComponents.customData(), tag); + wrappedItemStack.finishEdit(); return wrappedItemStack.toBukkit(); } diff --git a/src/main/java/com/artillexstudios/axminions/utils/Direction.java b/src/main/java/com/artillexstudios/axminions/utils/Direction.java new file mode 100644 index 0000000..558c9c0 --- /dev/null +++ b/src/main/java/com/artillexstudios/axminions/utils/Direction.java @@ -0,0 +1,18 @@ +package com.artillexstudios.axminions.utils; + +import org.bukkit.block.BlockFace; + +public enum Direction { + NORTH(180f, BlockFace.NORTH), + WEST(90f, BlockFace.WEST), + SOUTH(0f, BlockFace.SOUTH), + EAST(-90f, BlockFace.EAST); + + private final float yaw; + private final BlockFace face; + + Direction(float yaw, BlockFace face) { + this.yaw = yaw; + this.face = face; + } +}