From abc35bae98a09bed23ff97dda912a0cbc174ff0e Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 4 Dec 2023 22:41:46 +0800 Subject: [PATCH 01/42] feat: init universal inv design --- .../city/norain/slimefun4/utils/PDCUtil.java | 54 +++++++++++++++++++ .../slimefun4/utils/pdctype/UUIDType.java | 40 ++++++++++++++ .../items/androids/ProgrammableAndroid.java | 45 +++++++++++----- .../items/androids/menu/AndroidShareMenu.java | 11 +--- .../api/inventory/BlockMenuPreset.java | 4 ++ .../api/inventory/UniversalChestMenu.java | 39 ++++++++++++++ 6 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 src/main/java/city/norain/slimefun4/utils/PDCUtil.java create mode 100644 src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java create mode 100644 src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java diff --git a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java new file mode 100644 index 0000000000..3ccc4e18c4 --- /dev/null +++ b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java @@ -0,0 +1,54 @@ +package city.norain.slimefun4.utils; + +import city.norain.slimefun4.utils.pdctype.UUIDType; +import com.google.common.base.Preconditions; +import io.papermc.lib.PaperLib; +import java.util.UUID; +import javax.annotation.Nonnull; +import org.bukkit.NamespacedKey; +import org.bukkit.block.Block; +import org.bukkit.block.TileState; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class PDCUtil { + public static final PersistentDataType uuid = new UUIDType(); + + private PDCUtil() throws IllegalAccessException { + throw new IllegalAccessException("Utility Class"); + } + + public static void setValue(@Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key, @Nonnull Z value) { + var state = (TileState) PaperLib.getBlockState(block, false); + var container = state.getPersistentDataContainer(); + + setValue(container, type, key, value); + } + + public static void setValue(@Nonnull PersistentDataContainer container, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key, @Nonnull Z value) { + Preconditions.checkArgument(container != null, "Container cannot be null!"); + Preconditions.checkArgument(type != null, "PDC type cannot be null!"); + Preconditions.checkArgument(key != null, "PDC key cannot be null!"); + + container.set(key, type, value); + } + + public static Z getValue(@Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { + var state = (TileState) PaperLib.getBlockState(block, false); + var container = state.getPersistentDataContainer(); + + return getValue(container, type, key); + } + + public static Z getValue(@Nonnull PersistentDataContainer container, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { + Preconditions.checkArgument(container != null, "Container cannot be null!"); + Preconditions.checkArgument(type != null, "PDC type cannot be null!"); + Preconditions.checkArgument(key != null, "PDC key cannot be null!"); + + if (container.has(key, type)) { + return container.get(key, type); + } else { + return null; + } + } +} diff --git a/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java b/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java new file mode 100644 index 0000000000..7d2bddbf70 --- /dev/null +++ b/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java @@ -0,0 +1,40 @@ +package city.norain.slimefun4.utils.pdctype; + +import java.nio.ByteBuffer; +import java.util.UUID; +import javax.annotation.Nonnull; +import org.bukkit.persistence.PersistentDataAdapterContext; +import org.bukkit.persistence.PersistentDataType; + +public class UUIDType implements PersistentDataType { + + @Nonnull + @Override + public Class getPrimitiveType() { + return byte[].class; + } + + @Nonnull + @Override + public Class getComplexType() { + return UUID.class; + } + + @Nonnull + @Override + public byte [] toPrimitive(final UUID complex, @Nonnull final PersistentDataAdapterContext context) { + var bb = ByteBuffer.wrap(new byte[16]); + bb.putLong(complex.getMostSignificantBits()); + bb.putLong(complex.getLeastSignificantBits()); + return bb.array(); + } + + @Nonnull + @Override + public UUID fromPrimitive(@Nonnull final byte[] primitive, @Nonnull final PersistentDataAdapterContext context) { + var bb = ByteBuffer.wrap(primitive); + var mostBits = bb.getLong(); + var leastBits = bb.getLong(); + return new UUID(mostBits, leastBits); + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 340137fa85..4826ba8636 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -1,5 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.utils.PDCUtil; +import city.norain.slimefun4.utils.pdctype.UUIDType; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.chat.ChatInput; @@ -43,12 +45,14 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; import org.bukkit.Tag; import org.bukkit.block.Block; @@ -64,6 +68,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, RecipeDisplayItem { @@ -76,6 +81,14 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, private static final String DEFAULT_SCRIPT = "START-TURN_LEFT-REPEAT"; private static final int MAX_SCRIPT_LENGTH = 54; + private static final NamespacedKey OWNER_KEY = new NamespacedKey(Slimefun.instance(), "android_owner"); + private static final NamespacedKey UUID_KEY = new NamespacedKey(Slimefun.instance(), "android_uuid"); + private static final NamespacedKey SCRIPT_KEY = new NamespacedKey(Slimefun.instance(), "android_script"); + private static final NamespacedKey SCRIPT_INDEX_KEY = new NamespacedKey(Slimefun.instance(), "android_script_step"); + private static final NamespacedKey FUEL_KEY = new NamespacedKey(Slimefun.instance(), "android_fuel"); + private static final NamespacedKey ROTATION_KEY = new NamespacedKey(Slimefun.instance(), "android_rotation"); + private static final NamespacedKey STATUS_KEY = new NamespacedKey(Slimefun.instance(), "android_status"); + protected final List fuelTypes = new ArrayList<>(); protected final String texture; private final int tier; @@ -110,19 +123,21 @@ public boolean canOpen(Block b, Player p) { } @Override - public void newInstance(BlockMenu menu, Block b) { + public void newInstance(UniversalChestMenu menu, Block b) { menu.replaceExistingItem( 15, new CustomItemStack(HeadTexture.SCRIPT_START.getAsItemStack(), "&a启动/继续运行")); menu.addMenuClickHandler(15, (p, slot, item, action) -> { Slimefun.getLocalization().sendMessage(p, "android.started", true); - StorageCacheUtils.setData(b.getLocation(), "paused", "false"); + PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, true); + //StorageCacheUtils.setData(b.getLocation(), "paused", "false"); p.closeInventory(); return false; }); menu.replaceExistingItem(17, new CustomItemStack(HeadTexture.SCRIPT_PAUSE.getAsItemStack(), "&4暂停运行")); menu.addMenuClickHandler(17, (p, slot, item, action) -> { - StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); + //StorageCacheUtils.setData(b.getLocation(), "paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); return false; }); @@ -132,7 +147,8 @@ public void newInstance(BlockMenu menu, Block b) { new CustomItemStack( HeadTexture.ENERGY_REGULATOR.getAsItemStack(), "&b内存核心", "", "&8\u21E8 &7单击打开脚本编辑器")); menu.addMenuClickHandler(16, (p, slot, item, action) -> { - StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); + //StorageCacheUtils.setData(b.getLocation(), "paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); openScriptEditor(p, b); return false; @@ -146,7 +162,8 @@ public void newInstance(BlockMenu menu, Block b) { "", Slimefun.getLocalization().getMessage("android.access-manager.subtitle"))); menu.addMenuClickHandler(25, (p, slot, item, action) -> { - StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); + //StorageCacheUtils.setData(b.getLocation(), "paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); AndroidShareMenu.openShareMenu(p, b); return false; @@ -170,14 +187,17 @@ private BlockPlaceHandler onPlace() { public void onPlayerPlace(BlockPlaceEvent e) { Player p = e.getPlayer(); Block b = e.getBlock(); + UUID uuid = UUID.randomUUID(); - var blockData = StorageCacheUtils.getBlock(b.getLocation()); - blockData.setData("owner", p.getUniqueId().toString()); - blockData.setData("script", DEFAULT_SCRIPT); - blockData.setData("index", "0"); - blockData.setData("fuel", "0"); - blockData.setData("rotation", p.getFacing().getOppositeFace().toString()); - blockData.setData("paused", "true"); + // FIXME: create universal inv + + PDCUtil.setValue(b, PDCUtil.uuid, OWNER_KEY, p.getUniqueId()); + PDCUtil.setValue(b, PDCUtil.uuid, UUID_KEY, uuid); + PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); + PDCUtil.setValue(b, PersistentDataType.SHORT, SCRIPT_INDEX_KEY, (short) 0); + PDCUtil.setValue(b, PersistentDataType.INTEGER, FUEL_KEY, 0); + PDCUtil.setValue(b, PersistentDataType.STRING, ROTATION_KEY, p.getFacing().getOppositeFace().toString()); + PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, true); b.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { if (data instanceof Rotatable rotatable) { @@ -205,6 +225,7 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro return; } + // FIXME: use universal inv BlockMenu inv = blockData.getBlockMenu(); if (inv != null) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java index cf7e67925d..bf6f675fd9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java @@ -248,16 +248,7 @@ private static void setSharedUserData(@Nonnull BlockState state, @Nonnull String container.set(BLOCK_INFO_KEY, PersistentDataType.STRING, value); state.update(); } catch (Exception x) { - Slimefun.logger().log(Level.SEVERE, "Please check if your Server Software is up to date!"); - - String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName(); - Slimefun.logger() - .log( - Level.SEVERE, - () -> serverSoftware + " | " + Bukkit.getVersion() + " | " + Bukkit.getBukkitVersion()); - - Slimefun.logger() - .log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Android", x); + Slimefun.logger().log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Android", x); } } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java index 9f87ab50f9..742c0e7122 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java @@ -91,6 +91,10 @@ public void newInstance(@Nonnull BlockMenu menu, @Nonnull Block b) { // This method can optionally be overridden by implementations } + public void newInstance(@Nonnull UniversalChestMenu menu, @Nonnull Block b) { + // This method can optionally be overridden by implementations + } + public int[] getSlotsAccessedByItemTransport(DirtyChestMenu menu, ItemTransportFlow flow, ItemStack item) { // This method will default to that method, it can be overridden by subclasses though return getSlotsAccessedByItemTransport(flow); diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java new file mode 100644 index 0000000000..ef873478e1 --- /dev/null +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java @@ -0,0 +1,39 @@ +package me.mrCookieSlime.Slimefun.api.inventory; + +import java.util.UUID; +import javax.annotation.Nonnull; + +import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; +import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; +import org.bukkit.Location; +import org.bukkit.inventory.ItemStack; + +/** + * This class represents a universal chest menu + * which a menu located by certain identify id instead of location. + */ +public class UniversalChestMenu extends DirtyChestMenu { + private final UUID uuid; + + public UniversalChestMenu(@Nonnull BlockMenuPreset preset, @Nonnull UUID uuid) { + super(preset); + + this.uuid = uuid; + } + + public UniversalChestMenu(BlockMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { + super(preset); + this.uuid = uuid; + + for (int i = 0; i < contents.length; i++) { + var item = contents[i]; + if (item == null) { + continue; + } + addItem(i, item); + } + + preset.clone(this); + this.getContents(); + } +} From 78737b330e02bd914429e422e3b08b9071a6799a Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 4 Dec 2023 22:42:35 +0800 Subject: [PATCH 02/42] feat: init universal inv design --- .../city/norain/slimefun4/utils/PDCUtil.java | 20 +++++++++++++++---- .../slimefun4/utils/pdctype/UUIDType.java | 2 +- .../items/androids/ProgrammableAndroid.java | 15 ++++++++------ .../items/androids/menu/AndroidShareMenu.java | 4 ++-- .../api/inventory/UniversalChestMenu.java | 4 ---- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java index 3ccc4e18c4..1383aad263 100644 --- a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java +++ b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java @@ -18,14 +18,22 @@ private PDCUtil() throws IllegalAccessException { throw new IllegalAccessException("Utility Class"); } - public static void setValue(@Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key, @Nonnull Z value) { + public static void setValue( + @Nonnull Block block, + @Nonnull PersistentDataType type, + @Nonnull NamespacedKey key, + @Nonnull Z value) { var state = (TileState) PaperLib.getBlockState(block, false); var container = state.getPersistentDataContainer(); setValue(container, type, key, value); } - public static void setValue(@Nonnull PersistentDataContainer container, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key, @Nonnull Z value) { + public static void setValue( + @Nonnull PersistentDataContainer container, + @Nonnull PersistentDataType type, + @Nonnull NamespacedKey key, + @Nonnull Z value) { Preconditions.checkArgument(container != null, "Container cannot be null!"); Preconditions.checkArgument(type != null, "PDC type cannot be null!"); Preconditions.checkArgument(key != null, "PDC key cannot be null!"); @@ -33,14 +41,18 @@ public static void setValue(@Nonnull PersistentDataContainer container, @N container.set(key, type, value); } - public static Z getValue(@Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { + public static Z getValue( + @Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { var state = (TileState) PaperLib.getBlockState(block, false); var container = state.getPersistentDataContainer(); return getValue(container, type, key); } - public static Z getValue(@Nonnull PersistentDataContainer container, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { + public static Z getValue( + @Nonnull PersistentDataContainer container, + @Nonnull PersistentDataType type, + @Nonnull NamespacedKey key) { Preconditions.checkArgument(container != null, "Container cannot be null!"); Preconditions.checkArgument(type != null, "PDC type cannot be null!"); Preconditions.checkArgument(key != null, "PDC key cannot be null!"); diff --git a/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java b/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java index 7d2bddbf70..3c719e8f9c 100644 --- a/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java +++ b/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java @@ -22,7 +22,7 @@ public Class getComplexType() { @Nonnull @Override - public byte [] toPrimitive(final UUID complex, @Nonnull final PersistentDataAdapterContext context) { + public byte[] toPrimitive(final UUID complex, @Nonnull final PersistentDataAdapterContext context) { var bb = ByteBuffer.wrap(new byte[16]); bb.putLong(complex.getMostSignificantBits()); bb.putLong(complex.getLeastSignificantBits()); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 4826ba8636..0e75b04434 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -1,7 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; import city.norain.slimefun4.utils.PDCUtil; -import city.norain.slimefun4.utils.pdctype.UUIDType; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.chat.ChatInput; @@ -129,7 +128,7 @@ public void newInstance(UniversalChestMenu menu, Block b) { menu.addMenuClickHandler(15, (p, slot, item, action) -> { Slimefun.getLocalization().sendMessage(p, "android.started", true); PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, true); - //StorageCacheUtils.setData(b.getLocation(), "paused", "false"); + // StorageCacheUtils.setData(b.getLocation(), "paused", "false"); p.closeInventory(); return false; }); @@ -137,7 +136,7 @@ public void newInstance(UniversalChestMenu menu, Block b) { menu.replaceExistingItem(17, new CustomItemStack(HeadTexture.SCRIPT_PAUSE.getAsItemStack(), "&4暂停运行")); menu.addMenuClickHandler(17, (p, slot, item, action) -> { PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); - //StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + // StorageCacheUtils.setData(b.getLocation(), "paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); return false; }); @@ -148,7 +147,7 @@ public void newInstance(UniversalChestMenu menu, Block b) { HeadTexture.ENERGY_REGULATOR.getAsItemStack(), "&b内存核心", "", "&8\u21E8 &7单击打开脚本编辑器")); menu.addMenuClickHandler(16, (p, slot, item, action) -> { PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); - //StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + // StorageCacheUtils.setData(b.getLocation(), "paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); openScriptEditor(p, b); return false; @@ -163,7 +162,7 @@ public void newInstance(UniversalChestMenu menu, Block b) { Slimefun.getLocalization().getMessage("android.access-manager.subtitle"))); menu.addMenuClickHandler(25, (p, slot, item, action) -> { PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); - //StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + // StorageCacheUtils.setData(b.getLocation(), "paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); AndroidShareMenu.openShareMenu(p, b); return false; @@ -196,7 +195,11 @@ public void onPlayerPlace(BlockPlaceEvent e) { PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); PDCUtil.setValue(b, PersistentDataType.SHORT, SCRIPT_INDEX_KEY, (short) 0); PDCUtil.setValue(b, PersistentDataType.INTEGER, FUEL_KEY, 0); - PDCUtil.setValue(b, PersistentDataType.STRING, ROTATION_KEY, p.getFacing().getOppositeFace().toString()); + PDCUtil.setValue( + b, + PersistentDataType.STRING, + ROTATION_KEY, + p.getFacing().getOppositeFace().toString()); PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, true); b.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java index bf6f675fd9..c68e136c10 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/menu/AndroidShareMenu.java @@ -7,7 +7,6 @@ import io.github.thebusybiscuit.slimefun4.utils.ChatUtils; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; -import io.papermc.lib.PaperLib; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -248,7 +247,8 @@ private static void setSharedUserData(@Nonnull BlockState state, @Nonnull String container.set(BLOCK_INFO_KEY, PersistentDataType.STRING, value); state.update(); } catch (Exception x) { - Slimefun.logger().log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Android", x); + Slimefun.logger() + .log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Android", x); } } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java index ef873478e1..1ce2c684bc 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java @@ -2,10 +2,6 @@ import java.util.UUID; import javax.annotation.Nonnull; - -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; -import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; -import org.bukkit.Location; import org.bukkit.inventory.ItemStack; /** From cc74fa33255cd15ddf31b863d9bc6bc9a77808da Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 10 Dec 2023 16:44:51 +0800 Subject: [PATCH 03/42] feat: universal inventory progress --- .../storage/adapter/mysql/MysqlAdapter.java | 390 +++++++++--------- .../adapter/postgresql/PostgreSqlAdapter.java | 22 + .../adapter/sqlcommon/SqlCommonAdapter.java | 6 +- .../adapter/sqlcommon/SqlConstants.java | 3 + .../storage/adapter/sqlcommon/SqlUtils.java | 4 + .../storage/adapter/sqlite/SqliteAdapter.java | 21 + .../slimefun4/storage/common/DataScope.java | 3 +- .../slimefun4/storage/common/FieldKey.java | 7 +- .../controller/BlockDataController.java | 65 +++ 9 files changed, 333 insertions(+), 188 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java index 18ae9ffb44..163986f1ce 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java @@ -14,6 +14,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlCommonAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlUtils; @@ -39,6 +40,7 @@ public void initStorage(DataType type) { blockDataTable = SqlUtils.mapTable(DataScope.BLOCK_DATA, config.tablePrefix()); blockInvTable = SqlUtils.mapTable(DataScope.BLOCK_INVENTORY, config.tablePrefix()); chunkDataTable = SqlUtils.mapTable(DataScope.CHUNK_DATA, config.tablePrefix()); + universalInventoryTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); createBlockStorageTables(); } } @@ -71,40 +73,40 @@ public void setData(RecordKey key, RecordSet item) { } executeSql("INSERT INTO " - + mapTable(key.getScope()) - + " (" - + fieldStr.get() - + ") " - + "VALUES (" - + valStr - + ")" - + (updateFields.isEmpty() - ? "" - : " ON DUPLICATE KEY UPDATE " - + String.join( - ", ", - updateFields.stream() - .map(field -> { - var val = item.get(field); - if (val == null) { - throw new IllegalArgumentException( - "Cannot find value in RecordSet for the specific key: " - + field); - } - return SqlUtils.buildKvStr(field, val); - }) - .toList())) - + ";"); + + mapTable(key.getScope()) + + " (" + + fieldStr.get() + + ") " + + "VALUES (" + + valStr + + ")" + + (updateFields.isEmpty() + ? "" + : " ON DUPLICATE KEY UPDATE " + + String.join( + ", ", + updateFields.stream() + .map(field -> { + var val = item.get(field); + if (val == null) { + throw new IllegalArgumentException( + "Cannot find value in RecordSet for the specific key: " + + field); + } + return SqlUtils.buildKvStr(field, val); + }) + .toList())) + + ";"); } @Override public List getData(RecordKey key, boolean distinct) { return executeQuery((distinct ? "SELECT DISTINCT " : "SELECT ") - + SqlUtils.buildFieldStr(key.getFields()).orElse("*") - + " FROM " - + mapTable(key.getScope()) - + SqlUtils.buildConditionStr(key.getConditions()) - + ";"); + + SqlUtils.buildFieldStr(key.getFields()).orElse("*") + + " FROM " + + mapTable(key.getScope()) + + SqlUtils.buildConditionStr(key.getConditions()) + + ";"); } @Override @@ -124,192 +126,212 @@ private void createBlockStorageTables() { createBlockDataTable(); createBlockInvTable(); createChunkDataTable(); + createUniversalInventoryTable(); } private void createProfileTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + profileTable - + "(" - + FIELD_PLAYER_UUID - + " CHAR(64) PRIMARY KEY NOT NULL, " - + FIELD_PLAYER_NAME - + " CHAR(64) NOT NULL, " - + FIELD_BACKPACK_NUM - + " INT UNSIGNED DEFAULT 0, " - + "INDEX index_player_name (" - + FIELD_PLAYER_NAME - + ")" - + ");"); + + profileTable + + "(" + + FIELD_PLAYER_UUID + + " CHAR(64) PRIMARY KEY NOT NULL, " + + FIELD_PLAYER_NAME + + " CHAR(64) NOT NULL, " + + FIELD_BACKPACK_NUM + + " INT UNSIGNED DEFAULT 0, " + + "INDEX index_player_name (" + + FIELD_PLAYER_NAME + + ")" + + ");"); } private void createResearchTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + researchTable - + "(" - + FIELD_PLAYER_UUID - + " CHAR(64) NOT NULL, " - + FIELD_RESEARCH_KEY - + " CHAR(64) NOT NULL, " - + "FOREIGN KEY (" - + FIELD_PLAYER_UUID - + ") " - + "REFERENCES " - + profileTable - + "(" - + FIELD_PLAYER_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "INDEX index_player_research (" - + FIELD_PLAYER_UUID - + ", " - + FIELD_RESEARCH_KEY - + ")" - + ");"); + + researchTable + + "(" + + FIELD_PLAYER_UUID + + " CHAR(64) NOT NULL, " + + FIELD_RESEARCH_KEY + + " CHAR(64) NOT NULL, " + + "FOREIGN KEY (" + + FIELD_PLAYER_UUID + + ") " + + "REFERENCES " + + profileTable + + "(" + + FIELD_PLAYER_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "INDEX index_player_research (" + + FIELD_PLAYER_UUID + + ", " + + FIELD_RESEARCH_KEY + + ")" + + ");"); } private void createBackpackTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + backpackTable - + "(" - + FIELD_BACKPACK_ID - + " CHAR(64) PRIMARY KEY NOT NULL, " - + FIELD_PLAYER_UUID - + " CHAR(64) NOT NULL, " - + FIELD_BACKPACK_NUM - + " INT UNSIGNED NOT NULL, " - + FIELD_BACKPACK_NAME - + " CHAR(64) NULL, " - + FIELD_BACKPACK_SIZE - + " TINYINT UNSIGNED NOT NULL, " - + "FOREIGN KEY (" - + FIELD_PLAYER_UUID - + ") " - + "REFERENCES " - + profileTable - + "(" - + FIELD_PLAYER_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "INDEX index_player_backpack (" - + FIELD_PLAYER_UUID - + ", " - + FIELD_BACKPACK_NUM - + ")" - + ");"); + + backpackTable + + "(" + + FIELD_BACKPACK_ID + + " CHAR(64) PRIMARY KEY NOT NULL, " + + FIELD_PLAYER_UUID + + " CHAR(64) NOT NULL, " + + FIELD_BACKPACK_NUM + + " INT UNSIGNED NOT NULL, " + + FIELD_BACKPACK_NAME + + " CHAR(64) NULL, " + + FIELD_BACKPACK_SIZE + + " TINYINT UNSIGNED NOT NULL, " + + "FOREIGN KEY (" + + FIELD_PLAYER_UUID + + ") " + + "REFERENCES " + + profileTable + + "(" + + FIELD_PLAYER_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "INDEX index_player_backpack (" + + FIELD_PLAYER_UUID + + ", " + + FIELD_BACKPACK_NUM + + ")" + + ");"); } private void createBackpackInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + bpInvTable - + "(" - + FIELD_BACKPACK_ID - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_BACKPACK_ID - + ") " - + "REFERENCES " - + backpackTable - + "(" - + FIELD_BACKPACK_ID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_BACKPACK_ID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");"); + + bpInvTable + + "(" + + FIELD_BACKPACK_ID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_BACKPACK_ID + + ") " + + "REFERENCES " + + backpackTable + + "(" + + FIELD_BACKPACK_ID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_BACKPACK_ID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } private void createBlockRecordTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + blockRecordTable - + "(" - + FIELD_LOCATION - + " CHAR(64) PRIMARY KEY NOT NULL, " - + FIELD_CHUNK - + " CHAR(64) NOT NULL, " - + FIELD_SLIMEFUN_ID - + " CHAR(64) NOT NULL, " - + "INDEX index_ticking (" - + FIELD_CHUNK - + ")" - + ");"); + + blockRecordTable + + "(" + + FIELD_LOCATION + + " CHAR(64) PRIMARY KEY NOT NULL, " + + FIELD_CHUNK + + " CHAR(64) NOT NULL, " + + FIELD_SLIMEFUN_ID + + " CHAR(64) NOT NULL, " + + "INDEX index_ticking (" + + FIELD_CHUNK + + ")" + + ");"); } private void createBlockDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + blockDataTable - + "(" - + FIELD_LOCATION - + " CHAR(64) NOT NULL, " - + FIELD_DATA_KEY - + " CHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_LOCATION - + ") " - + "REFERENCES " - + blockRecordTable - + "(" - + FIELD_LOCATION - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_LOCATION - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + blockDataTable + + "(" + + FIELD_LOCATION + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_LOCATION + + ") " + + "REFERENCES " + + blockRecordTable + + "(" + + FIELD_LOCATION + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_LOCATION + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); } private void createChunkDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + chunkDataTable - + "(" - + FIELD_CHUNK - + " CHAR(64) NOT NULL, " - + FIELD_DATA_KEY - + " CHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "PRIMARY KEY (" - + FIELD_CHUNK - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + chunkDataTable + + "(" + + FIELD_CHUNK + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "PRIMARY KEY (" + + FIELD_CHUNK + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); + } + + private void createUniversalInventoryTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalInventoryTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");" + ); } private void createBlockInvTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + blockInvTable - + "(" - + FIELD_LOCATION - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_LOCATION - + ") " - + "REFERENCES " - + blockRecordTable - + "(" - + FIELD_LOCATION - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_LOCATION - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");"); + + blockInvTable + + "(" + + FIELD_LOCATION + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_LOCATION + + ") " + + "REFERENCES " + + blockRecordTable + + "(" + + FIELD_LOCATION + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_LOCATION + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index e1b550552e..04f8b2dbca 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -14,6 +14,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlCommonAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlUtils; @@ -41,6 +42,7 @@ public void initStorage(DataType type) { blockDataTable = SqlUtils.mapTable(DataScope.BLOCK_DATA, config.tablePrefix()); blockInvTable = SqlUtils.mapTable(DataScope.BLOCK_INVENTORY, config.tablePrefix()); chunkDataTable = SqlUtils.mapTable(DataScope.CHUNK_DATA, config.tablePrefix()); + universalInventoryTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); createBlockStorageTables(); } } @@ -136,6 +138,7 @@ private void createBlockStorageTables() { createBlockDataTable(); createBlockInvTable(); createChunkDataTable(); + createUniversalInventoryTable(); } private void createProfileTable() { @@ -328,4 +331,23 @@ private void createBlockInvTable() { + ")" + ");"); } + + private void createUniversalInventoryTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalInventoryTable + + "(" + + FIELD_UNIVERSAL_UUID + + " UUID NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");" + ); + } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java index 781ba5d789..facf1f3e79 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java @@ -14,7 +14,7 @@ public abstract class SqlCommonAdapter implements IDataSourceAdapter { protected HikariDataSource ds; protected String profileTable, researchTable, backpackTable, bpInvTable; - protected String blockRecordTable, blockDataTable, chunkDataTable, blockInvTable; + protected String blockRecordTable, blockDataTable, chunkDataTable, blockInvTable, universalInventoryTable; protected T config; @Override @@ -42,7 +42,7 @@ protected List executeQuery(String sql) { if (Debug.hasTestCase(TestCase.DATABASE)) { throw new IllegalStateException("An exception thrown while executing sql: " + sql, e); } else { - throw new IllegalStateException("在操作数据库出现了问题, 原始 SQL 语句: " + sql); + throw new IllegalStateException("在查询数据库出现了问题, 原始 SQL 语句: " + sql); } } } @@ -57,6 +57,7 @@ protected String mapTable(DataScope scope) { case CHUNK_DATA -> chunkDataTable; case BLOCK_DATA -> blockDataTable; case BLOCK_RECORD -> blockRecordTable; + case UNIVERSAL_INVENTORY -> universalInventoryTable; case NONE -> throw new IllegalArgumentException("NONE cannot be a storage data scope!"); }; } @@ -73,5 +74,6 @@ public void shutdown() { blockRecordTable = null; chunkDataTable = null; blockInvTable = null; + universalInventoryTable = null; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java index 49c32ad6fa..58c491d525 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java @@ -9,6 +9,7 @@ public interface SqlConstants { String TABLE_NAME_BLOCK_DATA = "block_data"; String TABLE_NAME_CHUNK_DATA = "chunk_data"; String TABLE_NAME_BLOCK_INVENTORY = "block_inventory"; + String TABLE_NAME_UNIVERSAL_INVENTORY = "universal_inventory"; String FIELD_PLAYER_UUID = "p_uuid"; String FIELD_PLAYER_NAME = "p_name"; @@ -29,4 +30,6 @@ public interface SqlConstants { String FIELD_DATA_KEY = "data_key"; String FIELD_DATA_VALUE = "data_val"; + + String FIELD_UNIVERSAL_UUID = "universal_uuid"; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java index d3ed2b8c23..dff255bb57 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java @@ -14,6 +14,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_BACKPACK; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_BACKPACK_INVENTORY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_BLOCK_DATA; @@ -22,6 +23,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_CHUNK_DATA; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_PLAYER_PROFILE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_PLAYER_RESEARCH; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_UNIVERSAL_INVENTORY; import com.xzavier0722.mc.plugin.slimefun4.storage.common.DataScope; import com.xzavier0722.mc.plugin.slimefun4.storage.common.FieldKey; @@ -60,6 +62,7 @@ public class SqlUtils { fieldMap.put(FieldKey.SLIMEFUN_ID, FIELD_SLIMEFUN_ID); fieldMap.put(FieldKey.DATA_KEY, FIELD_DATA_KEY); fieldMap.put(FieldKey.DATA_VALUE, FIELD_DATA_VALUE); + fieldMap.put(FieldKey.UNIVERSAL_UUID, FIELD_UNIVERSAL_UUID); mapper = new FieldMapper<>(fieldMap); } @@ -73,6 +76,7 @@ public static String mapTable(DataScope scope) { case BLOCK_DATA -> TABLE_NAME_BLOCK_DATA; case CHUNK_DATA -> TABLE_NAME_CHUNK_DATA; case BLOCK_INVENTORY -> TABLE_NAME_BLOCK_INVENTORY; + case UNIVERSAL_INVENTORY -> TABLE_NAME_UNIVERSAL_INVENTORY; case NONE -> throw new IllegalArgumentException("NONE cannot be a storage data scope!"); }; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index fcc3f4de93..f53c5023cf 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -14,6 +14,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlCommonAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlUtils; @@ -116,6 +117,7 @@ private void createBlockStorageTables() { createBlockDataTable(); createBlockInvTable(); createChunkDataTable(); + createUniversalInventoryTable(); } private void createProfileTable() { @@ -311,6 +313,25 @@ private void createBlockInvTable() { + ");"); } + private void createUniversalInventoryTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY) + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");" + ); + } + public synchronized void executeSql(String sql) { super.executeSql(sql); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java index 5795346ec6..3c96e113cd 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java @@ -9,7 +9,8 @@ public enum DataScope { BLOCK_RECORD(new FieldKey[] {FieldKey.LOCATION}), BLOCK_DATA(new FieldKey[] {FieldKey.LOCATION, FieldKey.DATA_KEY}), CHUNK_DATA(new FieldKey[] {FieldKey.CHUNK, FieldKey.DATA_KEY}), - BLOCK_INVENTORY(new FieldKey[] {FieldKey.LOCATION, FieldKey.INVENTORY_SLOT}); + BLOCK_INVENTORY(new FieldKey[] {FieldKey.LOCATION, FieldKey.INVENTORY_SLOT}), + UNIVERSAL_INVENTORY(new FieldKey[] {FieldKey.UNIVERSAL_UUID, FieldKey.INVENTORY_SLOT}); private final FieldKey[] primaryKeys; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java index 4dfd86b370..9720cfa301 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java @@ -20,7 +20,12 @@ public enum FieldKey { SLIMEFUN_ID, DATA_KEY, - DATA_VALUE; + DATA_VALUE, + + /** + * Represents uuid of universal inventory + */ + UNIVERSAL_UUID; private final boolean isNumType; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 55b09dcf09..05764f32f6 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -31,6 +32,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -537,6 +539,37 @@ public Set getAllLoadedChunkData() { return new HashSet<>(loadedChunk.values()); } + public UniversalChestMenu createUniversalInventory() { + // TODO: Fill code + return null; + } + + @Nullable + public UniversalChestMenu getUniversalInventory(@Nonnull UUID universalID) { + // TODO: Fill code + return null; + } + + public void saveUniversalInventory(@Nonnull UUID universalID, UniversalChestMenu menu) { + var newInv = menu.getContents(); + List> lastSave; + if (newInv == null) { + lastSave = invSnapshots.remove(universalID.toString()); + if (lastSave == null) { + return; + } + } else { + lastSave = invSnapshots.put(universalID.toString(), InvStorageUtils.getInvSnapshot(newInv)); + } + + var changed = InvStorageUtils.getChangedSlots(lastSave, newInv); + if (changed.isEmpty()) { + return; + } + + changed.forEach(slot -> scheduleDelayedUniversalInvUpdate(universalID, menu, slot)); + } + private void scheduleDelayedBlockInvUpdate(SlimefunBlockData blockData, int slot) { var scopeKey = new LocationKey(DataScope.NONE, blockData.getLocation()); var reqKey = new RecordKey(DataScope.BLOCK_INVENTORY); @@ -568,6 +601,38 @@ private void scheduleBlockInvUpdate(ScopeKey scopeKey, RecordKey reqKey, String } } + private void scheduleDelayedUniversalInvUpdate(UUID uuid, UniversalChestMenu menu, int slot) { + var scopeKey = new UUIDKey(DataScope.NONE, uuid); + var reqKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); + reqKey.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); + reqKey.addCondition(FieldKey.INVENTORY_SLOT, slot + ""); + reqKey.addField(FieldKey.INVENTORY_ITEM); + + if (enableDelayedSaving) { + scheduleDelayedUpdateTask( + new LinkedKey(scopeKey, reqKey), + () -> scheduleUniversalInvUpdate( + scopeKey, reqKey, uuid, menu.getContents(), slot)); + } else { + scheduleUniversalInvUpdate(scopeKey, reqKey, uuid, menu.getContents(), slot); + } + } + + private void scheduleUniversalInvUpdate(ScopeKey scopeKey, RecordKey reqKey, UUID uuid, ItemStack[] inv, int slot) { + var item = inv != null && slot < inv.length ? inv[slot] : null; + + if (item == null) { + scheduleDeleteTask(scopeKey, reqKey, true); + } else { + var data = new RecordSet(); + data.put(FieldKey.UNIVERSAL_UUID, uuid.toString()); + data.put(FieldKey.INVENTORY_SLOT, slot + ""); + data.put(FieldKey.INVENTORY_ITEM, item); + scheduleWriteTask(scopeKey, reqKey, data, true); + } + } + + @Override public void shutdown() { saveAllBlockInventories(); From 343af6c0c491a3bfd1f3433caa10110d27e50ade Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 19 Dec 2023 00:35:19 +0800 Subject: [PATCH 04/42] chore: sync up --- .../storage/adapter/mysql/MysqlAdapter.java | 397 +++++++++--------- .../adapter/postgresql/PostgreSqlAdapter.java | 29 +- .../storage/adapter/sqlite/SqliteAdapter.java | 29 +- .../controller/BlockDataController.java | 9 +- 4 files changed, 229 insertions(+), 235 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java index 163986f1ce..8f6d960a2b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java @@ -73,40 +73,40 @@ public void setData(RecordKey key, RecordSet item) { } executeSql("INSERT INTO " - + mapTable(key.getScope()) - + " (" - + fieldStr.get() - + ") " - + "VALUES (" - + valStr - + ")" - + (updateFields.isEmpty() - ? "" - : " ON DUPLICATE KEY UPDATE " - + String.join( - ", ", - updateFields.stream() - .map(field -> { - var val = item.get(field); - if (val == null) { - throw new IllegalArgumentException( - "Cannot find value in RecordSet for the specific key: " - + field); - } - return SqlUtils.buildKvStr(field, val); - }) - .toList())) - + ";"); + + mapTable(key.getScope()) + + " (" + + fieldStr.get() + + ") " + + "VALUES (" + + valStr + + ")" + + (updateFields.isEmpty() + ? "" + : " ON DUPLICATE KEY UPDATE " + + String.join( + ", ", + updateFields.stream() + .map(field -> { + var val = item.get(field); + if (val == null) { + throw new IllegalArgumentException( + "Cannot find value in RecordSet for the specific key: " + + field); + } + return SqlUtils.buildKvStr(field, val); + }) + .toList())) + + ";"); } @Override public List getData(RecordKey key, boolean distinct) { return executeQuery((distinct ? "SELECT DISTINCT " : "SELECT ") - + SqlUtils.buildFieldStr(key.getFields()).orElse("*") - + " FROM " - + mapTable(key.getScope()) - + SqlUtils.buildConditionStr(key.getConditions()) - + ";"); + + SqlUtils.buildFieldStr(key.getFields()).orElse("*") + + " FROM " + + mapTable(key.getScope()) + + SqlUtils.buildConditionStr(key.getConditions()) + + ";"); } @Override @@ -131,207 +131,206 @@ private void createBlockStorageTables() { private void createProfileTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + profileTable - + "(" - + FIELD_PLAYER_UUID - + " CHAR(64) PRIMARY KEY NOT NULL, " - + FIELD_PLAYER_NAME - + " CHAR(64) NOT NULL, " - + FIELD_BACKPACK_NUM - + " INT UNSIGNED DEFAULT 0, " - + "INDEX index_player_name (" - + FIELD_PLAYER_NAME - + ")" - + ");"); + + profileTable + + "(" + + FIELD_PLAYER_UUID + + " CHAR(64) PRIMARY KEY NOT NULL, " + + FIELD_PLAYER_NAME + + " CHAR(64) NOT NULL, " + + FIELD_BACKPACK_NUM + + " INT UNSIGNED DEFAULT 0, " + + "INDEX index_player_name (" + + FIELD_PLAYER_NAME + + ")" + + ");"); } private void createResearchTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + researchTable - + "(" - + FIELD_PLAYER_UUID - + " CHAR(64) NOT NULL, " - + FIELD_RESEARCH_KEY - + " CHAR(64) NOT NULL, " - + "FOREIGN KEY (" - + FIELD_PLAYER_UUID - + ") " - + "REFERENCES " - + profileTable - + "(" - + FIELD_PLAYER_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "INDEX index_player_research (" - + FIELD_PLAYER_UUID - + ", " - + FIELD_RESEARCH_KEY - + ")" - + ");"); + + researchTable + + "(" + + FIELD_PLAYER_UUID + + " CHAR(64) NOT NULL, " + + FIELD_RESEARCH_KEY + + " CHAR(64) NOT NULL, " + + "FOREIGN KEY (" + + FIELD_PLAYER_UUID + + ") " + + "REFERENCES " + + profileTable + + "(" + + FIELD_PLAYER_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "INDEX index_player_research (" + + FIELD_PLAYER_UUID + + ", " + + FIELD_RESEARCH_KEY + + ")" + + ");"); } private void createBackpackTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + backpackTable - + "(" - + FIELD_BACKPACK_ID - + " CHAR(64) PRIMARY KEY NOT NULL, " - + FIELD_PLAYER_UUID - + " CHAR(64) NOT NULL, " - + FIELD_BACKPACK_NUM - + " INT UNSIGNED NOT NULL, " - + FIELD_BACKPACK_NAME - + " CHAR(64) NULL, " - + FIELD_BACKPACK_SIZE - + " TINYINT UNSIGNED NOT NULL, " - + "FOREIGN KEY (" - + FIELD_PLAYER_UUID - + ") " - + "REFERENCES " - + profileTable - + "(" - + FIELD_PLAYER_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "INDEX index_player_backpack (" - + FIELD_PLAYER_UUID - + ", " - + FIELD_BACKPACK_NUM - + ")" - + ");"); + + backpackTable + + "(" + + FIELD_BACKPACK_ID + + " CHAR(64) PRIMARY KEY NOT NULL, " + + FIELD_PLAYER_UUID + + " CHAR(64) NOT NULL, " + + FIELD_BACKPACK_NUM + + " INT UNSIGNED NOT NULL, " + + FIELD_BACKPACK_NAME + + " CHAR(64) NULL, " + + FIELD_BACKPACK_SIZE + + " TINYINT UNSIGNED NOT NULL, " + + "FOREIGN KEY (" + + FIELD_PLAYER_UUID + + ") " + + "REFERENCES " + + profileTable + + "(" + + FIELD_PLAYER_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "INDEX index_player_backpack (" + + FIELD_PLAYER_UUID + + ", " + + FIELD_BACKPACK_NUM + + ")" + + ");"); } private void createBackpackInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + bpInvTable - + "(" - + FIELD_BACKPACK_ID - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_BACKPACK_ID - + ") " - + "REFERENCES " - + backpackTable - + "(" - + FIELD_BACKPACK_ID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_BACKPACK_ID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");"); + + bpInvTable + + "(" + + FIELD_BACKPACK_ID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_BACKPACK_ID + + ") " + + "REFERENCES " + + backpackTable + + "(" + + FIELD_BACKPACK_ID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_BACKPACK_ID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } private void createBlockRecordTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + blockRecordTable - + "(" - + FIELD_LOCATION - + " CHAR(64) PRIMARY KEY NOT NULL, " - + FIELD_CHUNK - + " CHAR(64) NOT NULL, " - + FIELD_SLIMEFUN_ID - + " CHAR(64) NOT NULL, " - + "INDEX index_ticking (" - + FIELD_CHUNK - + ")" - + ");"); + + blockRecordTable + + "(" + + FIELD_LOCATION + + " CHAR(64) PRIMARY KEY NOT NULL, " + + FIELD_CHUNK + + " CHAR(64) NOT NULL, " + + FIELD_SLIMEFUN_ID + + " CHAR(64) NOT NULL, " + + "INDEX index_ticking (" + + FIELD_CHUNK + + ")" + + ");"); } private void createBlockDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + blockDataTable - + "(" - + FIELD_LOCATION - + " CHAR(64) NOT NULL, " - + FIELD_DATA_KEY - + " CHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_LOCATION - + ") " - + "REFERENCES " - + blockRecordTable - + "(" - + FIELD_LOCATION - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_LOCATION - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + blockDataTable + + "(" + + FIELD_LOCATION + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_LOCATION + + ") " + + "REFERENCES " + + blockRecordTable + + "(" + + FIELD_LOCATION + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_LOCATION + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); } private void createChunkDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + chunkDataTable - + "(" - + FIELD_CHUNK - + " CHAR(64) NOT NULL, " - + FIELD_DATA_KEY - + " CHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "PRIMARY KEY (" - + FIELD_CHUNK - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + chunkDataTable + + "(" + + FIELD_CHUNK + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "PRIMARY KEY (" + + FIELD_CHUNK + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); } private void createUniversalInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalInventoryTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL," - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");" - ); + + universalInventoryTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } private void createBlockInvTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + blockInvTable - + "(" - + FIELD_LOCATION - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_LOCATION - + ") " - + "REFERENCES " - + blockRecordTable - + "(" - + FIELD_LOCATION - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_LOCATION - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");"); + + blockInvTable + + "(" + + FIELD_LOCATION + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_LOCATION + + ") " + + "REFERENCES " + + blockRecordTable + + "(" + + FIELD_LOCATION + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_LOCATION + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index 04f8b2dbca..45fb7b9e22 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -334,20 +334,19 @@ private void createBlockInvTable() { private void createUniversalInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalInventoryTable - + "(" - + FIELD_UNIVERSAL_UUID - + " UUID NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL," - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");" - ); + + universalInventoryTable + + "(" + + FIELD_UNIVERSAL_UUID + + " UUID NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index f53c5023cf..e30f702710 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -315,21 +315,20 @@ private void createBlockInvTable() { private void createUniversalInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY) - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL," - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");" - ); + + SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY) + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " TEXT NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } public synchronized void executeSql(String sql) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 05764f32f6..a54378abe9 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -544,8 +544,7 @@ public UniversalChestMenu createUniversalInventory() { return null; } - @Nullable - public UniversalChestMenu getUniversalInventory(@Nonnull UUID universalID) { + @Nullable public UniversalChestMenu getUniversalInventory(@Nonnull UUID universalID) { // TODO: Fill code return null; } @@ -610,9 +609,8 @@ private void scheduleDelayedUniversalInvUpdate(UUID uuid, UniversalChestMenu men if (enableDelayedSaving) { scheduleDelayedUpdateTask( - new LinkedKey(scopeKey, reqKey), - () -> scheduleUniversalInvUpdate( - scopeKey, reqKey, uuid, menu.getContents(), slot)); + new LinkedKey(scopeKey, reqKey), + () -> scheduleUniversalInvUpdate(scopeKey, reqKey, uuid, menu.getContents(), slot)); } else { scheduleUniversalInvUpdate(scopeKey, reqKey, uuid, menu.getContents(), slot); } @@ -632,7 +630,6 @@ private void scheduleUniversalInvUpdate(ScopeKey scopeKey, RecordKey reqKey, UUI } } - @Override public void shutdown() { saveAllBlockInventories(); From 0fdd70cbe06d13c96dbc6a50b8bbb2be14229b39 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 18 Jan 2024 19:39:26 +0800 Subject: [PATCH 05/42] feat(universal): fill universal menu api --- .../controller/BlockDataController.java | 4 +- .../storage/util/StorageCacheUtils.java | 7 +++ .../items/androids/ProgrammableAndroid.java | 26 ++++++----- .../general/Inventory/ChestMenu.java | 2 + .../api/inventory/BlockMenuPreset.java | 8 +--- .../api/inventory/DirtyChestMenu.java | 21 --------- .../api/inventory/UniversalChestMenu.java | 28 ++++++++++-- .../api/inventory/UniversalMenuPreset.java | 45 +++++++++++++++++++ 8 files changed, 97 insertions(+), 44 deletions(-) create mode 100644 src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 2e32e9be91..31cb89a4cb 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -585,12 +585,12 @@ public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) }); } - public UniversalChestMenu createUniversalInventory() { + public UniversalChestMenu createUniversalInventory(@Nonnull UUID uuid) { // TODO: Fill code return null; } - @Nullable public UniversalChestMenu getUniversalInventory(@Nonnull UUID universalID) { + @Nullable public UniversalChestMenu getUniversalInventory(@Nonnull UUID uuid) { // TODO: Fill code return null; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index f5fc4a6e8f..1632bc8399 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -7,9 +7,11 @@ import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.HashSet; import java.util.Set; +import java.util.UUID; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; import org.bukkit.Location; /** @@ -77,6 +79,11 @@ public static void removeData(Location loc, String key) { return blockData.getBlockMenu(); } + @ParametersAreNonnullByDefault + @Nullable public static UniversalChestMenu getUniversalMenu(UUID uuid) { + return Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); + } + public static void requestLoad(SlimefunBlockData blockData) { if (blockData.isDataLoaded()) { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 0e75b04434..53e3a135f4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -45,6 +45,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenuPreset; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; @@ -101,7 +102,7 @@ public ProgrammableAndroid( texture = item.getSkullTexture().orElse(null); registerDefaultFuelTypes(); - new BlockMenuPreset(getId(), "可编程式机器人") { + new UniversalMenuPreset(getId(), "可编程式机器人") { @Override public void init() { @@ -188,7 +189,7 @@ public void onPlayerPlace(BlockPlaceEvent e) { Block b = e.getBlock(); UUID uuid = UUID.randomUUID(); - // FIXME: create universal inv + Slimefun.getDatabaseManager().getBlockDataController().createUniversalInventory(uuid); PDCUtil.setValue(b, PDCUtil.uuid, OWNER_KEY, p.getUniqueId()); PDCUtil.setValue(b, PDCUtil.uuid, UUID_KEY, uuid); @@ -218,18 +219,17 @@ private BlockBreakHandler onBreak() { @Override public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List drops) { Block b = e.getBlock(); - var blockData = StorageCacheUtils.getBlock(b.getLocation()); - String owner = blockData.getData("owner"); + UUID owner = PDCUtil.getValue(b, PDCUtil.uuid, OWNER_KEY); + UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); if (!e.getPlayer().hasPermission("slimefun.android.bypass") - && !e.getPlayer().getUniqueId().toString().equals(owner)) { + && !e.getPlayer().getUniqueId().equals(owner)) { // The Player is not allowed to break this android e.setCancelled(true); return; } - // FIXME: use universal inv - BlockMenu inv = blockData.getBlockMenu(); + UniversalChestMenu inv = Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); if (inv != null) { inv.dropItems(b.getLocation(), 43); @@ -289,6 +289,7 @@ public void openScript(Player p, Block b, String sourceCode) { ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); + UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); menu.addItem( 0, @@ -298,7 +299,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(0, (pl, slot, item, action) -> { - BlockMenu inv = StorageCacheUtils.getMenu(b.getLocation()); + UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -333,7 +334,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(slot, (pl, s, item, action) -> { - BlockMenu inv = StorageCacheUtils.getMenu(b.getLocation()); + UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -579,6 +580,8 @@ public void openScriptEditor(Player p, Block b) { new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); + UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); + menu.addItem(1, new CustomItemStack(HeadTexture.SCRIPT_FORWARD.getAsItemStack(), "&2> 编辑脚本", "", "&a修改你现有的脚本")); menu.addMenuClickHandler(1, (pl, slot, item, action) -> { String script = StorageCacheUtils.getData(b.getLocation(), "script"); @@ -620,7 +623,7 @@ public void openScriptEditor(Player p, Block b) { menu.addItem(8, new CustomItemStack(HeadTexture.SCRIPT_LEFT.getAsItemStack(), "&6> 返回", "", "&7返回机器人控制面板")); menu.addMenuClickHandler(8, (pl, slot, item, action) -> { - BlockMenu inv = StorageCacheUtils.getMenu(b.getLocation()); + UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -995,7 +998,8 @@ public boolean onClick( public void addItems(Block b, ItemStack... items) { Validate.notNull(b, "The Block cannot be null."); - BlockMenu inv = StorageCacheUtils.getMenu(b.getLocation()); + UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); + UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); if (inv != null) { for (ItemStack item : items) { diff --git a/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java b/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java index 760d2efc3d..8df34f1568 100644 --- a/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java +++ b/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java @@ -9,6 +9,7 @@ import java.util.UUID; import java.util.concurrent.CopyOnWriteArraySet; import javax.annotation.Nonnull; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -26,6 +27,7 @@ public class ChestMenu extends SlimefunInventoryHolder { private boolean clickable; private boolean emptyClickable; + @Getter private String title; private List items; private Map handlers; diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java index 742c0e7122..9454918817 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java @@ -20,12 +20,12 @@ // This class will be deprecated, relocated and rewritten in a future version. public abstract class BlockMenuPreset extends ChestMenu { - private final Set occupiedSlots = new HashSet<>(); + final Set occupiedSlots = new HashSet<>(); private final String inventoryTitle; private final String id; // -1 means "automatically update according to the contents" - private int size = -1; + int size = -1; private boolean locked; @@ -91,10 +91,6 @@ public void newInstance(@Nonnull BlockMenu menu, @Nonnull Block b) { // This method can optionally be overridden by implementations } - public void newInstance(@Nonnull UniversalChestMenu menu, @Nonnull Block b) { - // This method can optionally be overridden by implementations - } - public int[] getSlotsAccessedByItemTransport(DirtyChestMenu menu, ItemTransportFlow flow, ItemStack item) { // This method will default to that method, it can be overridden by subclasses though return getSlotsAccessedByItemTransport(flow); diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java index 5cf98e3c93..24ecf9b111 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java @@ -80,12 +80,6 @@ public void close() { } public boolean fits(@Nonnull ItemStack item, int... slots) { - Debug.log( - TestCase.UTILS, - "DirtyChestMenu#fits - start check fits | item {} | slots {}", - StringUtil.itemStackToString(item), - Arrays.stream(slots).mapToObj(String::valueOf).collect(Collectors.joining(","))); - var isSfItem = SlimefunItem.getByItem(item) != null; var wrapper = ItemStackWrapper.wrap(item); var remain = item.getAmount(); @@ -97,15 +91,7 @@ public boolean fits(@Nonnull ItemStack item, int... slots) { return true; } - Debug.log( - TestCase.UTILS, - "DirtyChestMenu#fits - Now checking item | Slot {} | Item {}", - slot, - StringUtil.itemStackToString(slotItem)); - if (isSfItem) { - Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - Check slimefun item fits"); - if (!slotItem.hasItemMeta() || item.getType() != slotItem.getType() || !SlimefunUtils.isItemSimilar(slotItem, wrapper, true, false)) { @@ -114,14 +100,9 @@ public boolean fits(@Nonnull ItemStack item, int... slots) { var slotRemain = slotItem.getMaxStackSize() - slotItem.getAmount(); - Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - current slot remain: {}", slotRemain); - remain -= slotRemain; - Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - remaining amount: {}", remain); - if (remain <= 0) { - Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - check fits result (no remain): false"); return true; } } @@ -133,8 +114,6 @@ public boolean fits(@Nonnull ItemStack item, int... slots) { result = InvUtils.fits(toInventory(), wrapper, slots); } - Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - check fits result: {}", result); - return result; } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java index 1ce2c684bc..e89e4cda80 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java @@ -2,6 +2,8 @@ import java.util.UUID; import javax.annotation.Nonnull; +import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; +import org.bukkit.Location; import org.bukkit.inventory.ItemStack; /** @@ -11,13 +13,12 @@ public class UniversalChestMenu extends DirtyChestMenu { private final UUID uuid; - public UniversalChestMenu(@Nonnull BlockMenuPreset preset, @Nonnull UUID uuid) { + public UniversalChestMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { super(preset); - this.uuid = uuid; } - public UniversalChestMenu(BlockMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { + public UniversalChestMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { super(preset); this.uuid = uuid; @@ -30,6 +31,25 @@ public UniversalChestMenu(BlockMenuPreset preset, @Nonnull UUID uuid, ItemStack[ } preset.clone(this); - this.getContents(); + } + + /** + * This method drops the contents of this {@link BlockMenu} on the ground at the given + * {@link Location}. + * + * @param l + * Where to drop these items + * @param slots + * The slots of items that should be dropped + */ + public void dropItems(Location l, int... slots) { + for (int slot : slots) { + ItemStack item = getItemInSlot(slot); + + if (item != null) { + l.getWorld().dropItemNaturally(l, item); + replaceExistingItem(slot, null); + } + } } } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java new file mode 100644 index 0000000000..1ae031b049 --- /dev/null +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -0,0 +1,45 @@ +package me.mrCookieSlime.Slimefun.api.inventory; + +import javax.annotation.Nonnull; +import org.bukkit.block.Block; + +public abstract class UniversalMenuPreset extends BlockMenuPreset { + /** + * Creates a new ChestMenu with the specified + * Title + * + * @param title The title of the Menu + */ + public UniversalMenuPreset(@Nonnull String id, @Nonnull String title) { + super(id, title); + } + + public void newInstance(@Nonnull UniversalChestMenu menu, @Nonnull Block b) { + // This method can optionally be overridden by implementations + } + + protected void clone(@Nonnull DirtyChestMenu menu, @Nonnull Block block) { + menu.setPlayerInventoryClickable(true); + + for (int slot : occupiedSlots) { + menu.addItem(slot, getItemInSlot(slot)); + } + + if (size > -1) { + menu.addItem(size - 1, null); + } + + if (menu instanceof UniversalChestMenu universalChestMenu) { + newInstance(universalChestMenu, block); + } + + for (int slot = 0; slot < 54; slot++) { + if (getMenuClickHandler(slot) != null) { + menu.addMenuClickHandler(slot, getMenuClickHandler(slot)); + } + } + + menu.addMenuOpeningHandler(getMenuOpeningHandler()); + menu.addMenuCloseHandler(getMenuCloseHandler()); + } +} From 3ad782b5c84a3dd67febdd9a6885a775d4317b4e Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 9 Mar 2024 22:01:22 +0800 Subject: [PATCH 06/42] chore(api): fix scope --- .../Slimefun/api/inventory/BlockMenuPreset.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java index 9454918817..6daf660b52 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java @@ -7,6 +7,8 @@ import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; import org.apache.commons.lang.Validate; @@ -20,12 +22,12 @@ // This class will be deprecated, relocated and rewritten in a future version. public abstract class BlockMenuPreset extends ChestMenu { - final Set occupiedSlots = new HashSet<>(); + protected final Set occupiedSlots = new HashSet<>(); private final String inventoryTitle; private final String id; // -1 means "automatically update according to the contents" - int size = -1; + protected int size = -1; private boolean locked; From d91b633b35e45d6da5868d22321e24fcf0f908d1 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 11 Mar 2024 17:26:32 +0800 Subject: [PATCH 07/42] feat: sync up change (WIP) --- .../city/norain/slimefun4/utils/PDCUtil.java | 5 +- .../storage/adapter/mysql/MysqlAdapter.java | 4 +- .../adapter/postgresql/PostgreSqlAdapter.java | 4 +- .../adapter/sqlcommon/SqlCommonAdapter.java | 6 +- .../slimefun4/storage/common/DataScope.java | 1 + .../controller/BlockDataController.java | 40 +++++++--- .../controller/SlimefunUniversalData.java | 75 +++++++++++++++++++ .../storage/controller/StorageType.java | 1 - .../storage/util/StorageCacheUtils.java | 4 +- .../items/androids/ProgrammableAndroid.java | 33 ++++---- ...ersalChestMenu.java => UniversalMenu.java} | 11 ++- .../api/inventory/UniversalMenuPreset.java | 15 ++-- 12 files changed, 152 insertions(+), 47 deletions(-) create mode 100644 src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java rename src/main/java/me/mrCookieSlime/Slimefun/api/inventory/{UniversalChestMenu.java => UniversalMenu.java} (77%) diff --git a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java index 1383aad263..37118b3563 100644 --- a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java +++ b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java @@ -5,6 +5,7 @@ import io.papermc.lib.PaperLib; import java.util.UUID; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; import org.bukkit.block.TileState; @@ -12,7 +13,7 @@ import org.bukkit.persistence.PersistentDataType; public class PDCUtil { - public static final PersistentDataType uuid = new UUIDType(); + public static final PersistentDataType UUID_TYPE = new UUIDType(); private PDCUtil() throws IllegalAccessException { throw new IllegalAccessException("Utility Class"); @@ -41,6 +42,7 @@ public static void setValue( container.set(key, type, value); } + @Nullable public static Z getValue( @Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { var state = (TileState) PaperLib.getBlockState(block, false); @@ -49,6 +51,7 @@ public static Z getValue( return getValue(container, type, key); } + @Nullable public static Z getValue( @Nonnull PersistentDataContainer container, @Nonnull PersistentDataType type, diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java index 8f6d960a2b..cf84f4c6a6 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java @@ -40,7 +40,7 @@ public void initStorage(DataType type) { blockDataTable = SqlUtils.mapTable(DataScope.BLOCK_DATA, config.tablePrefix()); blockInvTable = SqlUtils.mapTable(DataScope.BLOCK_INVENTORY, config.tablePrefix()); chunkDataTable = SqlUtils.mapTable(DataScope.CHUNK_DATA, config.tablePrefix()); - universalInventoryTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); + universalInvTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); createBlockStorageTables(); } } @@ -291,7 +291,7 @@ private void createChunkDataTable() { private void createUniversalInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalInventoryTable + + universalInvTable + "(" + FIELD_UNIVERSAL_UUID + " CHAR(64) NOT NULL, " diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index 45fb7b9e22..4fb468c37b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -42,7 +42,7 @@ public void initStorage(DataType type) { blockDataTable = SqlUtils.mapTable(DataScope.BLOCK_DATA, config.tablePrefix()); blockInvTable = SqlUtils.mapTable(DataScope.BLOCK_INVENTORY, config.tablePrefix()); chunkDataTable = SqlUtils.mapTable(DataScope.CHUNK_DATA, config.tablePrefix()); - universalInventoryTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); + universalInvTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); createBlockStorageTables(); } } @@ -334,7 +334,7 @@ private void createBlockInvTable() { private void createUniversalInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalInventoryTable + + universalInvTable + "(" + FIELD_UNIVERSAL_UUID + " UUID NOT NULL, " diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java index facf1f3e79..5ec1aabaef 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java @@ -14,7 +14,7 @@ public abstract class SqlCommonAdapter implements IDataSourceAdapter { protected HikariDataSource ds; protected String profileTable, researchTable, backpackTable, bpInvTable; - protected String blockRecordTable, blockDataTable, chunkDataTable, blockInvTable, universalInventoryTable; + protected String blockRecordTable, blockDataTable, universalDataTable, chunkDataTable, blockInvTable, universalInvTable; protected T config; @Override @@ -57,7 +57,7 @@ protected String mapTable(DataScope scope) { case CHUNK_DATA -> chunkDataTable; case BLOCK_DATA -> blockDataTable; case BLOCK_RECORD -> blockRecordTable; - case UNIVERSAL_INVENTORY -> universalInventoryTable; + case UNIVERSAL_INVENTORY -> universalInvTable; case NONE -> throw new IllegalArgumentException("NONE cannot be a storage data scope!"); }; } @@ -74,6 +74,6 @@ public void shutdown() { blockRecordTable = null; chunkDataTable = null; blockInvTable = null; - universalInventoryTable = null; + universalInvTable = null; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java index 3c96e113cd..a459699033 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java @@ -10,6 +10,7 @@ public enum DataScope { BLOCK_DATA(new FieldKey[] {FieldKey.LOCATION, FieldKey.DATA_KEY}), CHUNK_DATA(new FieldKey[] {FieldKey.CHUNK, FieldKey.DATA_KEY}), BLOCK_INVENTORY(new FieldKey[] {FieldKey.LOCATION, FieldKey.INVENTORY_SLOT}), + UNIVERSAL_RECORD(new FieldKey[] {FieldKey.UNIVERSAL_UUID}), UNIVERSAL_INVENTORY(new FieldKey[] {FieldKey.UNIVERSAL_UUID, FieldKey.INVENTORY_SLOT}); private final FieldKey[] primaryKeys; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 7831b707bf..cb1bc527a3 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -32,7 +32,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -583,17 +583,12 @@ public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) }); } - public UniversalChestMenu createUniversalInventory(@Nonnull UUID uuid) { - // TODO: Fill code - return null; - } + @Nullable public UniversalMenu getUniversalInventory(@Nonnull UUID uuid) { - @Nullable public UniversalChestMenu getUniversalInventory(@Nonnull UUID uuid) { - // TODO: Fill code return null; } - public void saveUniversalInventory(@Nonnull UUID universalID, UniversalChestMenu menu) { + public void saveUniversalInventory(@Nonnull UUID universalID, UniversalMenu menu) { var newInv = menu.getContents(); List> lastSave; if (newInv == null) { @@ -670,7 +665,7 @@ private void scheduleBlockInvUpdate(ScopeKey scopeKey, RecordKey reqKey, String } } - private void scheduleDelayedUniversalInvUpdate(UUID uuid, UniversalChestMenu menu, int slot) { + private void scheduleDelayedUniversalInvUpdate(UUID uuid, UniversalMenu menu, int slot) { var scopeKey = new UUIDKey(DataScope.NONE, uuid); var reqKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); reqKey.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); @@ -724,6 +719,20 @@ void scheduleDelayedBlockDataUpdate(SlimefunBlockData blockData, String key) { } } + void scheduleDelayedUniversalDataUpdate(SlimefunUniversalData universalData, String key) { + var scopeKey = new UUIDKey(DataScope.NONE, universalData.getKey()); + var reqKey = new RecordKey(DataScope.UNIVERSAL_RECORD); + reqKey.addCondition(FieldKey.UNIVERSAL_UUID, universalData.getKey()); + reqKey.addCondition(FieldKey.DATA_KEY, key); + if (enableDelayedSaving) { + scheduleDelayedUpdateTask( + new LinkedKey(scopeKey, reqKey), + () -> scheduleUniversalDataUpdate(scopeKey, reqKey, universalData.getKey(), key, universalData.getData(key))); + } else { + scheduleUniversalDataUpdate(scopeKey, reqKey, universalData.getKey(), key, universalData.getData(key)); + } + } + private void removeDelayedBlockDataUpdates(ScopeKey scopeKey) { synchronized (delayedWriteTasks) { delayedWriteTasks @@ -745,6 +754,19 @@ private void scheduleBlockDataUpdate(ScopeKey scopeKey, RecordKey reqKey, String } } + private void scheduleUniversalDataUpdate(ScopeKey scopeKey, RecordKey reqKey, String uuid, String key, String val) { + if (val == null) { + scheduleDeleteTask(scopeKey, reqKey, false); + } else { + var data = new RecordSet(); + reqKey.addField(FieldKey.DATA_VALUE); + data.put(FieldKey.UNIVERSAL_UUID, uuid); + data.put(FieldKey.DATA_KEY, key); + data.put(FieldKey.DATA_VALUE, DataUtils.blockDataBase64(val)); + scheduleWriteTask(scopeKey, reqKey, data, true); + } + } + void scheduleDelayedChunkDataUpdate(SlimefunChunkData chunkData, String key) { var scopeKey = new ChunkKey(DataScope.NONE, chunkData.getChunk()); var reqKey = new RecordKey(DataScope.CHUNK_DATA); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java new file mode 100644 index 0000000000..41de5ec1a1 --- /dev/null +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -0,0 +1,75 @@ +package com.xzavier0722.mc.plugin.slimefun4.storage.controller; + +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import java.util.UUID; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.ParametersAreNullableByDefault; +import lombok.Getter; +import lombok.Setter; +import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; +import org.bukkit.inventory.ItemStack; + +public class SlimefunUniversalData extends ASlimefunDataContainer { + @Getter + private final String sfId; + @Setter + @Getter + private volatile UniversalMenu menu; + @Setter + @Getter + private volatile boolean pendingRemove = false; + + @ParametersAreNonnullByDefault + SlimefunUniversalData(UUID uuid, String sfId) { + super(uuid.toString()); + this.sfId = sfId; + } + + @ParametersAreNonnullByDefault + SlimefunUniversalData(UUID uuid, SlimefunUniversalData other) { + super(uuid.toString(), other); + this.sfId = other.sfId; + } + + @ParametersAreNonnullByDefault + public void setData(String key, String val) { + checkData(); + setCacheInternal(key, val, true); + Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, key); + } + + @ParametersAreNonnullByDefault + public void removeData(String key) { + if (removeCacheInternal(key) != null || !isDataLoaded()) { + Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, key); + } + } + + @Nullable public ItemStack[] getMenuContents() { + if (menu == null) { + return null; + } + var re = new ItemStack[54]; + var presetSlots = menu.getPreset().getPresetSlots(); + var inv = menu.toInventory().getContents(); + for (var i = 0; i < inv.length; i++) { + if (presetSlots.contains(i)) { + continue; + } + re[i] = inv[i]; + } + + return re; + } + + @Override + public String toString() { + return "SlimefunUniversalData [sfId=" + + sfId + + ", isPendingRemove=" + + pendingRemove + + "]"; + } +} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/StorageType.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/StorageType.java index 17852373b3..3e8579ecee 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/StorageType.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/StorageType.java @@ -3,6 +3,5 @@ public enum StorageType { MYSQL, SQLITE, - POSTGRESQL, } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 1632bc8399..1388a1c49b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -11,7 +11,7 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Location; /** @@ -80,7 +80,7 @@ public static void removeData(Location loc, String key) { } @ParametersAreNonnullByDefault - @Nullable public static UniversalChestMenu getUniversalMenu(UUID uuid) { + @Nullable public static UniversalMenu getUniversalMenu(UUID uuid) { return Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index d26cca34d3..488fb3fd9e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -45,7 +45,7 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalChestMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenuPreset; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; import org.apache.commons.lang.Validate; @@ -113,8 +113,9 @@ public void init() { @Override public boolean canOpen(Block b, Player p) { - boolean isOwner = p.getUniqueId().toString().equals(StorageCacheUtils.getData(b.getLocation(), "owner")) - || p.hasPermission("slimefun.android.bypass"); + UUID owner = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, OWNER_KEY); + + boolean isOwner = p.getUniqueId().equals(owner) || p.hasPermission("slimefun.android.bypass"); if (isOwner || AndroidShareMenu.isTrustedUser(b, p.getUniqueId())) { return true; @@ -125,7 +126,7 @@ public boolean canOpen(Block b, Player p) { } @Override - public void newInstance(UniversalChestMenu menu, Block b) { + public void newInstance(UniversalMenu menu, Block b) { menu.replaceExistingItem( 15, new CustomItemStack(HeadTexture.SCRIPT_START.getAsItemStack(), "&a启动/继续运行")); menu.addMenuClickHandler(15, (p, slot, item, action) -> { @@ -193,8 +194,8 @@ public void onPlayerPlace(BlockPlaceEvent e) { Slimefun.getDatabaseManager().getBlockDataController().createUniversalInventory(uuid); - PDCUtil.setValue(b, PDCUtil.uuid, OWNER_KEY, p.getUniqueId()); - PDCUtil.setValue(b, PDCUtil.uuid, UUID_KEY, uuid); + PDCUtil.setValue(b, PDCUtil.UUID_TYPE, OWNER_KEY, p.getUniqueId()); + PDCUtil.setValue(b, PDCUtil.UUID_TYPE, UUID_KEY, uuid); PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); PDCUtil.setValue(b, PersistentDataType.SHORT, SCRIPT_INDEX_KEY, (short) 0); PDCUtil.setValue(b, PersistentDataType.INTEGER, FUEL_KEY, 0); @@ -221,8 +222,8 @@ private BlockBreakHandler onBreak() { @Override public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List drops) { Block b = e.getBlock(); - UUID owner = PDCUtil.getValue(b, PDCUtil.uuid, OWNER_KEY); - UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); + UUID owner = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, OWNER_KEY); + UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); if (!e.getPlayer().hasPermission("slimefun.android.bypass") && !e.getPlayer().getUniqueId().equals(owner)) { @@ -231,7 +232,7 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro return; } - UniversalChestMenu inv = Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); + UniversalMenu inv = Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); if (inv != null) { inv.dropItems(b.getLocation(), 43); @@ -291,7 +292,7 @@ public void openScript(Player p, Block b, String sourceCode) { ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); - UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); + UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); menu.addItem( 0, @@ -301,7 +302,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(0, (pl, slot, item, action) -> { - UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -336,7 +337,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(slot, (pl, s, item, action) -> { - UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -582,7 +583,7 @@ public void openScriptEditor(Player p, Block b) { new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); - UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); + UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); menu.addItem(1, new CustomItemStack(HeadTexture.SCRIPT_FORWARD.getAsItemStack(), "&2> 编辑脚本", "", "&a修改你现有的脚本")); menu.addMenuClickHandler(1, (pl, slot, item, action) -> { @@ -625,7 +626,7 @@ public void openScriptEditor(Player p, Block b) { menu.addItem(8, new CustomItemStack(HeadTexture.SCRIPT_LEFT.getAsItemStack(), "&6> 返回", "", "&7返回机器人控制面板")); menu.addMenuClickHandler(8, (pl, slot, item, action) -> { - UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -1000,8 +1001,8 @@ public boolean onClick( public void addItems(Block b, ItemStack... items) { Validate.notNull(b, "The Block cannot be null."); - UUID uuid = PDCUtil.getValue(b, PDCUtil.uuid, UUID_KEY); - UniversalChestMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); if (inv != null) { for (ItemStack item : items) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java similarity index 77% rename from src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java rename to src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java index e89e4cda80..e80e6c02af 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalChestMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java @@ -2,7 +2,7 @@ import java.util.UUID; import javax.annotation.Nonnull; -import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; +import lombok.Getter; import org.bukkit.Location; import org.bukkit.inventory.ItemStack; @@ -10,15 +10,16 @@ * This class represents a universal chest menu * which a menu located by certain identify id instead of location. */ -public class UniversalChestMenu extends DirtyChestMenu { +public class UniversalMenu extends DirtyChestMenu { + @Getter private final UUID uuid; - public UniversalChestMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { super(preset); this.uuid = uuid; } - public UniversalChestMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { super(preset); this.uuid = uuid; @@ -29,8 +30,6 @@ public UniversalChestMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uui } addItem(i, item); } - - preset.clone(this); } /** diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java index 1ae031b049..dd2a2bedf5 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -1,6 +1,8 @@ package me.mrCookieSlime.Slimefun.api.inventory; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import org.bukkit.block.Block; public abstract class UniversalMenuPreset extends BlockMenuPreset { @@ -14,11 +16,11 @@ public UniversalMenuPreset(@Nonnull String id, @Nonnull String title) { super(id, title); } - public void newInstance(@Nonnull UniversalChestMenu menu, @Nonnull Block b) { + public void newInstance(@Nonnull UniversalMenu menu, @Nonnull Block b) { // This method can optionally be overridden by implementations } - protected void clone(@Nonnull DirtyChestMenu menu, @Nonnull Block block) { + protected void clone(@Nonnull UniversalMenu menu, @Nonnull Block b) { menu.setPlayerInventoryClickable(true); for (int slot : occupiedSlots) { @@ -29,9 +31,7 @@ protected void clone(@Nonnull DirtyChestMenu menu, @Nonnull Block block) { menu.addItem(size - 1, null); } - if (menu instanceof UniversalChestMenu universalChestMenu) { - newInstance(universalChestMenu, block); - } + newInstance(menu, b); for (int slot = 0; slot < 54; slot++) { if (getMenuClickHandler(slot) != null) { @@ -42,4 +42,9 @@ protected void clone(@Nonnull DirtyChestMenu menu, @Nonnull Block block) { menu.addMenuOpeningHandler(getMenuOpeningHandler()); menu.addMenuCloseHandler(getMenuCloseHandler()); } + + @Nullable + public static BlockMenuPreset getPreset(@Nullable String id) { + return id == null ? null : Slimefun.getRegistry().getMenuPresets().get(id); + } } From 4f154656d474abeee0c7ad0f260cd20acd6a38fa Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Fri, 29 Mar 2024 09:46:09 +0800 Subject: [PATCH 08/42] feat(unidata): universal data progress --- .../city/norain/slimefun4/utils/PDCUtil.java | 6 +- .../adapter/postgresql/PostgreSqlAdapter.java | 45 ++++++ .../adapter/sqlcommon/SqlCommonAdapter.java | 10 +- .../adapter/sqlcommon/SqlConstants.java | 2 + .../slimefun4/storage/common/DataScope.java | 1 + .../slimefun4/storage/common/FieldKey.java | 4 +- .../controller/BlockDataController.java | 131 ++++++++++++++++-- .../controller/SlimefunUniversalData.java | 29 ++-- .../storage/util/StorageCacheUtils.java | 8 +- .../core/attributes/UniversalDataSupport.java | 14 ++ .../NotCardinallyRotatable.java | 3 +- .../NotDiagonallyRotatable.java | 3 +- .../{ => rotations}/NotRotatable.java | 3 +- .../items/androids/ProgrammableAndroid.java | 23 +-- .../items/autocrafters/ArmorAutoCrafter.java | 2 +- .../autocrafters/EnhancedAutoCrafter.java | 2 +- .../autocrafters/VanillaAutoCrafter.java | 2 +- .../items/cargo/CargoConnectorNode.java | 2 +- .../items/cargo/CargoManager.java | 2 +- .../implementation/items/cargo/TrashCan.java | 2 +- .../items/electric/EnergyConnector.java | 2 +- .../items/electric/EnergyRegulator.java | 2 +- .../electric/generators/CoalGenerator.java | 2 +- .../generators/CombustionGenerator.java | 2 +- .../electric/generators/LavaGenerator.java | 2 +- .../generators/MagnesiumGenerator.java | 2 +- .../electric/machines/ElectricPress.java | 2 +- .../machines/entities/ExpCollector.java | 2 +- .../implementation/items/geo/GEOMiner.java | 1 + .../implementation/items/geo/GEOScanner.java | 2 +- .../implementation/items/geo/OilPump.java | 2 +- .../items/gps/GPSControlPanel.java | 2 +- .../items/gps/GPSTransmitter.java | 2 +- .../listeners/BlockListener.java | 19 ++- .../general/Inventory/ChestMenu.java | 2 + .../api/inventory/BlockMenuPreset.java | 2 - .../api/inventory/DirtyChestMenu.java | 5 - .../api/inventory/UniversalMenuPreset.java | 14 +- 38 files changed, 287 insertions(+), 74 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java rename src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/{ => rotations}/NotCardinallyRotatable.java (85%) rename src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/{ => rotations}/NotDiagonallyRotatable.java (86%) rename src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/{ => rotations}/NotRotatable.java (73%) diff --git a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java index 37118b3563..cb06f59646 100644 --- a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java +++ b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java @@ -42,8 +42,7 @@ public static void setValue( container.set(key, type, value); } - @Nullable - public static Z getValue( + @Nullable public static Z getValue( @Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { var state = (TileState) PaperLib.getBlockState(block, false); var container = state.getPersistentDataContainer(); @@ -51,8 +50,7 @@ public static Z getValue( return getValue(container, type, key); } - @Nullable - public static Z getValue( + @Nullable public static Z getValue( @Nonnull PersistentDataContainer container, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index 4fb468c37b..cb80db0e4c 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -9,6 +9,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; @@ -139,6 +140,7 @@ private void createBlockStorageTables() { createBlockInvTable(); createChunkDataTable(); createUniversalInventoryTable(); + createUniversalRecordTable(); } private void createProfileTable() { @@ -349,4 +351,47 @@ private void createUniversalInventoryTable() { + ")" + ");"); } + + private void createUniversalRecordTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + " UUID NOT NULL, " + + FIELD_SLIMEFUN_ID + + " TEXT NOT NULL, " + + FIELD_LAST_PRESENT + + " TEXT NOT NULL, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ")" + + ");"); + } + + private void createUniversalDataTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalDataTable + + "(" + + FIELD_UNIVERSAL_UUID + + " UUID NOT NULL, " + + FIELD_DATA_KEY + + " VARCHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_UNIVERSAL_UUID + + ") " + + "REFERENCES " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); + } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java index 5ec1aabaef..53638ac88e 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java @@ -14,7 +14,13 @@ public abstract class SqlCommonAdapter implements IDataSourceAdapter { protected HikariDataSource ds; protected String profileTable, researchTable, backpackTable, bpInvTable; - protected String blockRecordTable, blockDataTable, universalDataTable, chunkDataTable, blockInvTable, universalInvTable; + protected String blockRecordTable, + blockDataTable, + universalRecordTable, + universalDataTable, + chunkDataTable, + blockInvTable, + universalInvTable; protected T config; @Override @@ -58,6 +64,8 @@ protected String mapTable(DataScope scope) { case BLOCK_DATA -> blockDataTable; case BLOCK_RECORD -> blockRecordTable; case UNIVERSAL_INVENTORY -> universalInvTable; + case UNIVERSAL_RECORD -> universalRecordTable; + case UNIVERSAL_DATA -> universalDataTable; case NONE -> throw new IllegalArgumentException("NONE cannot be a storage data scope!"); }; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java index 58c491d525..2833b4301e 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java @@ -32,4 +32,6 @@ public interface SqlConstants { String FIELD_DATA_VALUE = "data_val"; String FIELD_UNIVERSAL_UUID = "universal_uuid"; + + String FIELD_LAST_PRESENT = "last_present"; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java index a459699033..9cb322da71 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/DataScope.java @@ -11,6 +11,7 @@ public enum DataScope { CHUNK_DATA(new FieldKey[] {FieldKey.CHUNK, FieldKey.DATA_KEY}), BLOCK_INVENTORY(new FieldKey[] {FieldKey.LOCATION, FieldKey.INVENTORY_SLOT}), UNIVERSAL_RECORD(new FieldKey[] {FieldKey.UNIVERSAL_UUID}), + UNIVERSAL_DATA(new FieldKey[] {FieldKey.UNIVERSAL_UUID, FieldKey.DATA_KEY}), UNIVERSAL_INVENTORY(new FieldKey[] {FieldKey.UNIVERSAL_UUID, FieldKey.INVENTORY_SLOT}); private final FieldKey[] primaryKeys; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java index 9720cfa301..a3e9e1065c 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java @@ -25,7 +25,9 @@ public enum FieldKey { /** * Represents uuid of universal inventory */ - UNIVERSAL_UUID; + UNIVERSAL_UUID, + + LAST_PRESENT; private final boolean isNumType; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index cb1bc527a3..b30e72fd81 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -33,6 +33,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenuPreset; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -45,6 +46,7 @@ public class BlockDataController extends ADataController { private final Map delayedWriteTasks; private final Map loadedChunk; + private final Map loadedUniversalData; private final Map>> invSnapshots; private final ScopedLock lock; private boolean enableDelayedSaving = false; @@ -57,6 +59,7 @@ public class BlockDataController extends ADataController { super(DataType.BLOCK_STORAGE); delayedWriteTasks = new HashMap<>(); loadedChunk = new ConcurrentHashMap<>(); + loadedUniversalData = new ConcurrentHashMap<>(); invSnapshots = new ConcurrentHashMap<>(); lock = new ScopedLock(); } @@ -156,6 +159,27 @@ public SlimefunBlockData createBlock(Location l, String sfId) { return re; } + @Nonnull + @ParametersAreNonnullByDefault + public SlimefunUniversalData createUniversalData(Location l, String sfId) { + checkDestroy(); + + var uuid = UUID.randomUUID(); + var uniData = new SlimefunUniversalData(uuid, l, sfId); + + uniData.setIsDataLoaded(true); + loadedUniversalData.put(uuid, uniData); + + var preset = UniversalMenuPreset.getPreset(sfId); + if (preset != null) { + uniData.setUniversalMenu(new UniversalMenu(preset, uuid)); + } + + Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uuid, sfId); + + return uniData; + } + void saveNewBlock(Location l, String sfId) { var lKey = LocationUtils.getLocKey(l); @@ -172,6 +196,24 @@ void saveNewBlock(Location l, String sfId) { scheduleWriteTask(scopeKey, key, data, true); } + /** + * Save certain universal data + * + * @param uuid universal data uuid + * @param sfId the item universal data represents + */ + void saveUniversalData(UUID uuid, String sfId) { + var key = new RecordKey(DataScope.UNIVERSAL_RECORD); + + var data = new RecordSet(); + data.put(FieldKey.UNIVERSAL_UUID, uuid.toString()); + data.put(FieldKey.SLIMEFUN_ID, sfId); + + var scopeKey = new UUIDKey(DataScope.NONE, uuid); + removeDelayedBlockDataUpdates(scopeKey); // Shouldn't have.. But for safe.. + scheduleWriteTask(scopeKey, key, data, true); + } + /** * Remove slimefun block data at specific location * @@ -199,6 +241,29 @@ public void removeBlock(Location l) { } } + public void removeUniversalData(UUID uuid) { + checkDestroy(); + + var toRemove = loadedUniversalData.get(uuid); + + if (toRemove == null) { + return; + } + + if (!toRemove.isDataLoaded()) { + return; + } + + var menu = toRemove.getUniversalMenu(); + if (menu != null) { + InventoryUtil.closeInventory(menu.toInventory()); + } + + if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { + Slimefun.getTickerTask().disableTicker(toRemove.getLastPresent()); + } + } + void removeBlockDirectly(Location l) { checkDestroy(); var scopeKey = new LocationKey(DataScope.NONE, l); @@ -248,9 +313,9 @@ public SlimefunBlockData getBlockData(Location l) { } /** - * Get slimefun block data at specific location async + * Get slimefun block data at specific location asynchronous * - * @param l slimefun block location {@link Location} + * @param l slimefun block location {@link Location} * @param callback operation when block data fetched {@link IAsyncReadCallback} */ public void getBlockDataAsync(Location l, IAsyncReadCallback callback) { @@ -267,6 +332,51 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { return getBlockDataFromCache(LocationUtils.getChunkKey(l.getChunk()), LocationUtils.getLocKey(l)); } + /** + * Get slimefun universal data + * + * @param uuid universal data uuid {@link UUID} + */ + @Nullable public SlimefunUniversalData getUniversalData(@Nonnull UUID uuid) { + checkDestroy(); + + var key = new RecordKey(DataScope.UNIVERSAL_RECORD); + key.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); + key.addField(FieldKey.SLIMEFUN_ID); + key.addField(FieldKey.LAST_PRESENT); + + var result = getData(key); + + return result.isEmpty() + ? null + : new SlimefunUniversalData( + uuid, + LocationUtils.toLocation(result.get(0).get(FieldKey.LAST_PRESENT)), + result.get(0).get(FieldKey.SLIMEFUN_ID)); + } + + /** + * Get slimefun universal data asynchronous + * + * @param uuid universal data uuid {@link UUID} + * @param callback operation when block data fetched {@link IAsyncReadCallback} + */ + public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback callback) { + scheduleReadTask(() -> invokeCallback(callback, getUniversalData(uuid))); + } + + /** + * Get slimefun universal data from cache + * + * @param uuid universal data uuid {@link UUID} + */ + @Nullable public SlimefunUniversalData getUniversalDataFromCache(@Nonnull UUID uuid) { + checkDestroy(); + + var cache = loadedUniversalData.get(uuid); + return cache != null ? cache : getUniversalData(uuid); + } + /** * Move block data to specific location *

@@ -583,11 +693,6 @@ public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) }); } - @Nullable public UniversalMenu getUniversalInventory(@Nonnull UUID uuid) { - - return null; - } - public void saveUniversalInventory(@Nonnull UUID universalID, UniversalMenu menu) { var newInv = menu.getContents(); List> lastSave; @@ -665,6 +770,13 @@ private void scheduleBlockInvUpdate(ScopeKey scopeKey, RecordKey reqKey, String } } + /** + * Save universal inventory by async way + * + * @param uuid Universal Inventory UUID + * @param menu Universal menu + * @param slot updated item slot + */ private void scheduleDelayedUniversalInvUpdate(UUID uuid, UniversalMenu menu, int slot) { var scopeKey = new UUIDKey(DataScope.NONE, uuid); var reqKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); @@ -726,8 +838,9 @@ void scheduleDelayedUniversalDataUpdate(SlimefunUniversalData universalData, Str reqKey.addCondition(FieldKey.DATA_KEY, key); if (enableDelayedSaving) { scheduleDelayedUpdateTask( - new LinkedKey(scopeKey, reqKey), - () -> scheduleUniversalDataUpdate(scopeKey, reqKey, universalData.getKey(), key, universalData.getData(key))); + new LinkedKey(scopeKey, reqKey), + () -> scheduleUniversalDataUpdate( + scopeKey, reqKey, universalData.getKey(), key, universalData.getData(key))); } else { scheduleUniversalDataUpdate(scopeKey, reqKey, universalData.getKey(), key, universalData.getData(key)); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index 41de5ec1a1..c7f8cecc04 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -4,32 +4,39 @@ import java.util.UUID; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.ParametersAreNullableByDefault; import lombok.Getter; import lombok.Setter; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; +import org.bukkit.Location; import org.bukkit.inventory.ItemStack; public class SlimefunUniversalData extends ASlimefunDataContainer { @Getter private final String sfId; + @Setter @Getter - private volatile UniversalMenu menu; + private volatile UniversalMenu universalMenu; + + @Setter + @Getter + private volatile Location lastPresent; + @Setter @Getter private volatile boolean pendingRemove = false; @ParametersAreNonnullByDefault - SlimefunUniversalData(UUID uuid, String sfId) { + SlimefunUniversalData(UUID uuid, Location location, String sfId) { super(uuid.toString()); + this.lastPresent = location; this.sfId = sfId; } @ParametersAreNonnullByDefault - SlimefunUniversalData(UUID uuid, SlimefunUniversalData other) { + SlimefunUniversalData(UUID uuid, Location location, SlimefunUniversalData other) { super(uuid.toString(), other); + this.lastPresent = location; this.sfId = other.sfId; } @@ -48,12 +55,12 @@ public void removeData(String key) { } @Nullable public ItemStack[] getMenuContents() { - if (menu == null) { + if (universalMenu == null) { return null; } var re = new ItemStack[54]; - var presetSlots = menu.getPreset().getPresetSlots(); - var inv = menu.toInventory().getContents(); + var presetSlots = universalMenu.getPreset().getPresetSlots(); + var inv = universalMenu.toInventory().getContents(); for (var i = 0; i < inv.length; i++) { if (presetSlots.contains(i)) { continue; @@ -66,10 +73,6 @@ public void removeData(String key) { @Override public String toString() { - return "SlimefunUniversalData [sfId=" - + sfId - + ", isPendingRemove=" - + pendingRemove - + "]"; + return "SlimefunUniversalData [sfId=" + sfId + ", isPendingRemove=" + pendingRemove + "]"; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 1388a1c49b..3729926482 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -81,7 +81,13 @@ public static void removeData(Location loc, String key) { @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(UUID uuid) { - return Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); + var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalData(uuid); + + if (uniData == null) { + return null; + } + + return uniData.getUniversalMenu(); } public static void requestLoad(SlimefunBlockData blockData) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java new file mode 100644 index 0000000000..bf9cee8b5a --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java @@ -0,0 +1,14 @@ +package io.github.thebusybiscuit.slimefun4.core.attributes; + +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; + +/** + * This attribute represents {@link SlimefunItem} support store + * {@link SlimefunUniversalData} + * + * @author NoRainCity + * + * @see SlimefunUniversalData + */ +public interface UniversalDataSupport {} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotCardinallyRotatable.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotCardinallyRotatable.java similarity index 85% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotCardinallyRotatable.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotCardinallyRotatable.java index a4ebd320c8..46b3886140 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotCardinallyRotatable.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotCardinallyRotatable.java @@ -1,6 +1,7 @@ -package io.github.thebusybiscuit.slimefun4.core.attributes; +package io.github.thebusybiscuit.slimefun4.core.attributes.rotations; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute; import org.bukkit.block.BlockFace; /** diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotDiagonallyRotatable.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotDiagonallyRotatable.java similarity index 86% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotDiagonallyRotatable.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotDiagonallyRotatable.java index 478dfee1b5..68249f1f65 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotDiagonallyRotatable.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotDiagonallyRotatable.java @@ -1,6 +1,7 @@ -package io.github.thebusybiscuit.slimefun4.core.attributes; +package io.github.thebusybiscuit.slimefun4.core.attributes.rotations; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute; import org.bukkit.block.BlockFace; /** diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotRotatable.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotRotatable.java similarity index 73% rename from src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotRotatable.java rename to src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotRotatable.java index b8b9f26f89..f3fc095b26 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/NotRotatable.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/rotations/NotRotatable.java @@ -1,6 +1,7 @@ -package io.github.thebusybiscuit.slimefun4.core.attributes; +package io.github.thebusybiscuit.slimefun4.core.attributes.rotations; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.ItemAttribute; import org.bukkit.block.BlockFace; /** diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 488fb3fd9e..7b5cd89fa0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -15,8 +15,9 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; @@ -72,7 +73,7 @@ import org.bukkit.persistence.PersistentDataType; public class ProgrammableAndroid extends SlimefunItem - implements InventoryBlock, RecipeDisplayItem, NotDiagonallyRotatable { + implements InventoryBlock, RecipeDisplayItem, NotDiagonallyRotatable, UniversalDataSupport { private static final List POSSIBLE_ROTATIONS = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST); @@ -192,8 +193,6 @@ public void onPlayerPlace(BlockPlaceEvent e) { Block b = e.getBlock(); UUID uuid = UUID.randomUUID(); - Slimefun.getDatabaseManager().getBlockDataController().createUniversalInventory(uuid); - PDCUtil.setValue(b, PDCUtil.UUID_TYPE, OWNER_KEY, p.getUniqueId()); PDCUtil.setValue(b, PDCUtil.UUID_TYPE, UUID_KEY, uuid); PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); @@ -232,11 +231,15 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro return; } - UniversalMenu inv = Slimefun.getDatabaseManager().getBlockDataController().getUniversalInventory(uuid); + var uniData = + Slimefun.getDatabaseManager().getBlockDataController().getUniversalData(uuid); - if (inv != null) { - inv.dropItems(b.getLocation(), 43); - inv.dropItems(b.getLocation(), getOutputSlots()); + if (uniData != null) { + var menu = uniData.getUniversalMenu(); + if (menu != null) { + menu.dropItems(b.getLocation(), 43); + menu.dropItems(b.getLocation(), getOutputSlots()); + } } } }; @@ -294,6 +297,10 @@ public void openScript(Player p, Block b, String sourceCode) { menu.setEmptySlotsClickable(false); UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); + if (uuid == null) { + throw new IllegalStateException("Android missing uuid"); + } + menu.addItem( 0, new CustomItemStack( diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/ArmorAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/ArmorAutoCrafter.java index 1db215b68e..9b007a5dc9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/ArmorAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/ArmorAutoCrafter.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.ArmorForge; import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.inventory.ItemStack; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/EnhancedAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/EnhancedAutoCrafter.java index 9c8d72a952..b1dbd80658 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/EnhancedAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/EnhancedAutoCrafter.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.EnhancedCraftingTable; import io.github.thebusybiscuit.slimefun4.implementation.listeners.AutoCrafterListener; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java index a141837ee0..bf063758a6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java @@ -6,7 +6,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService; import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoConnectorNode.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoConnectorNode.java index 821214896c..9de124b4c6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoConnectorNode.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoConnectorNode.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.core.networks.cargo.CargoNet; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoManager.java index 967f2e4a27..a53f3d3689 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoManager.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/CargoManager.java @@ -8,7 +8,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.core.networks.cargo.CargoNet; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/TrashCan.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/TrashCan.java index 1b24c6aa63..8a6348acc3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/TrashCan.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/cargo/TrashCan.java @@ -6,7 +6,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyConnector.java index 3793dae395..cc9fde2972 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyConnector.java @@ -5,7 +5,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyRegulator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyRegulator.java index fd79a39c8e..307ad2f4b2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyRegulator.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/EnergyRegulator.java @@ -7,7 +7,7 @@ import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; import io.github.thebusybiscuit.slimefun4.core.attributes.HologramOwner; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java index f44b2d1ffa..0d1877edc6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CoalGenerator.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CombustionGenerator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CombustionGenerator.java index e3704158e7..2e4fc2aec2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CombustionGenerator.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/CombustionGenerator.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/LavaGenerator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/LavaGenerator.java index 965ff85d61..df4b97d4a3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/LavaGenerator.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/LavaGenerator.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/MagnesiumGenerator.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/MagnesiumGenerator.java index ea3a4852cc..23dd4a2e5c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/MagnesiumGenerator.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/generators/MagnesiumGenerator.java @@ -3,7 +3,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricPress.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricPress.java index 505d4a1a7a..678e85f9a3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricPress.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/ElectricPress.java @@ -5,8 +5,8 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/entities/ExpCollector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/entities/ExpCollector.java index 8b9b5c0887..ae6c14e975 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/entities/ExpCollector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/electric/machines/entities/ExpCollector.java @@ -9,7 +9,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java index c100c8aca7..0628980599 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOMiner.java @@ -13,6 +13,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.*; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; import io.github.thebusybiscuit.slimefun4.core.machines.MachineProcessor; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOScanner.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOScanner.java index ac5ccaec46..fccb0a776d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOScanner.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/GEOScanner.java @@ -4,7 +4,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/OilPump.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/OilPump.java index 6b5d9b0545..358e7a7fa3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/OilPump.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/geo/OilPump.java @@ -5,8 +5,8 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSControlPanel.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSControlPanel.java index ea0cd06f6a..7b56fa0ecf 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSControlPanel.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSControlPanel.java @@ -4,7 +4,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSTransmitter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSTransmitter.java index eb8603509c..f0cb60ae89 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSTransmitter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/gps/GPSTransmitter.java @@ -7,7 +7,7 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 03f3c99983..65c5a6d30e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -9,10 +9,11 @@ import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockBreakEvent; import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotCardinallyRotatable; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotCardinallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; +import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler; @@ -143,9 +144,15 @@ public void onBlockPlace(BlockPlaceEvent e) { var placeEvent = new SlimefunBlockPlaceEvent(e.getPlayer(), item, e.getBlock(), sfItem); Bukkit.getPluginManager().callEvent(placeEvent); - Slimefun.getDatabaseManager() - .getBlockDataController() - .createBlock(e.getBlock().getLocation(), sfItem.getId()); + if (sfItem instanceof UniversalDataSupport) { + Slimefun.getDatabaseManager() + .getBlockDataController() + .createUniversalData(e.getBlock().getLocation(), sfItem.getId()); + } else { + Slimefun.getDatabaseManager() + .getBlockDataController() + .createBlock(e.getBlock().getLocation(), sfItem.getId()); + } sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); } } diff --git a/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java b/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java index 8df34f1568..5ace74c950 100644 --- a/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java +++ b/src/main/java/me/mrCookieSlime/CSCoreLibPlugin/general/Inventory/ChestMenu.java @@ -27,8 +27,10 @@ public class ChestMenu extends SlimefunInventoryHolder { private boolean clickable; private boolean emptyClickable; + @Getter private String title; + private List items; private Map handlers; private MenuOpeningHandler open; diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java index 6daf660b52..bd643ee41d 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/BlockMenuPreset.java @@ -7,8 +7,6 @@ import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import lombok.Getter; -import lombok.Setter; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; import org.apache.commons.lang.Validate; diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java index 24ecf9b111..38bbf9ff45 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/DirtyChestMenu.java @@ -1,17 +1,12 @@ package me.mrCookieSlime.Slimefun.api.inventory; -import city.norain.slimefun4.utils.StringUtil; import io.github.bakedlibs.dough.inventory.InvUtils; import io.github.bakedlibs.dough.items.CustomItemStack; import io.github.bakedlibs.dough.items.ItemUtils; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.core.debug.Debug; -import io.github.thebusybiscuit.slimefun4.core.debug.TestCase; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper; import java.util.ArrayList; -import java.util.Arrays; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu; diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java index dd2a2bedf5..b5a9814b82 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -43,8 +43,16 @@ protected void clone(@Nonnull UniversalMenu menu, @Nonnull Block b) { menu.addMenuCloseHandler(getMenuCloseHandler()); } - @Nullable - public static BlockMenuPreset getPreset(@Nullable String id) { - return id == null ? null : Slimefun.getRegistry().getMenuPresets().get(id); + @Nullable public static UniversalMenuPreset getPreset(@Nullable String id) { + if (id == null) { + return null; + } else { + var preset = Slimefun.getRegistry().getMenuPresets().get(id); + if (preset instanceof UniversalMenuPreset uniPreset) { + return uniPreset; + } else { + return null; + } + } } } From fe71242c8734a70150fb4734736f9901613e68c1 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Fri, 29 Mar 2024 09:50:24 +0800 Subject: [PATCH 09/42] fix(githook): fix git hook not cleanup code properly --- .git-hooks/pre-commit | 2 +- .../adapter/postgresql/PostgreSqlAdapter.java | 46 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.git-hooks/pre-commit b/.git-hooks/pre-commit index 6b17c8c3c5..d234525d79 100644 --- a/.git-hooks/pre-commit +++ b/.git-hooks/pre-commit @@ -3,7 +3,7 @@ echo "[pre-commit check]" echo -n "Checking code format with spotless: " -mvn spotless:apply > /tmp/spotless.out 2>&1 +mvn spotless:check > /tmp/spotless.out 2>&1 RETURN_VALUE=$? if [ $RETURN_VALUE -gt 0 ] then diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index cb80db0e4c..25be59456d 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -370,28 +370,28 @@ private void createUniversalRecordTable() { private void createUniversalDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalDataTable - + "(" - + FIELD_UNIVERSAL_UUID - + " UUID NOT NULL, " - + FIELD_DATA_KEY - + " VARCHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_UNIVERSAL_UUID - + ") " - + "REFERENCES " - + universalRecordTable - + "(" - + FIELD_UNIVERSAL_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + universalDataTable + + "(" + + FIELD_UNIVERSAL_UUID + + " UUID NOT NULL, " + + FIELD_DATA_KEY + + " VARCHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_UNIVERSAL_UUID + + ") " + + "REFERENCES " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); } } From 01a31586a8c99d05ac3eaae45a122882c54f94a1 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Fri, 29 Mar 2024 09:59:41 +0800 Subject: [PATCH 10/42] fix: missing scope cover --- .../slimefun4/storage/adapter/sqlcommon/SqlConstants.java | 2 ++ .../plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java index 2833b4301e..dc113a43b7 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java @@ -10,6 +10,8 @@ public interface SqlConstants { String TABLE_NAME_CHUNK_DATA = "chunk_data"; String TABLE_NAME_BLOCK_INVENTORY = "block_inventory"; String TABLE_NAME_UNIVERSAL_INVENTORY = "universal_inventory"; + String TABLE_NAME_UNIVERSAL_RECORD = "universal_record"; + String TABLE_NAME_UNIVERSAL_DATA = "universal_data"; String FIELD_PLAYER_UUID = "p_uuid"; String FIELD_PLAYER_NAME = "p_name"; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java index dff255bb57..40ee578a3b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java @@ -23,7 +23,9 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_CHUNK_DATA; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_PLAYER_PROFILE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_PLAYER_RESEARCH; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_UNIVERSAL_DATA; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_UNIVERSAL_INVENTORY; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_UNIVERSAL_RECORD; import com.xzavier0722.mc.plugin.slimefun4.storage.common.DataScope; import com.xzavier0722.mc.plugin.slimefun4.storage.common.FieldKey; @@ -77,6 +79,8 @@ public static String mapTable(DataScope scope) { case CHUNK_DATA -> TABLE_NAME_CHUNK_DATA; case BLOCK_INVENTORY -> TABLE_NAME_BLOCK_INVENTORY; case UNIVERSAL_INVENTORY -> TABLE_NAME_UNIVERSAL_INVENTORY; + case UNIVERSAL_RECORD -> TABLE_NAME_UNIVERSAL_RECORD; + case UNIVERSAL_DATA -> TABLE_NAME_UNIVERSAL_DATA; case NONE -> throw new IllegalArgumentException("NONE cannot be a storage data scope!"); }; } From 28b4df493e5b0af35cc2bad9ada1e895a9c29e74 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 30 Mar 2024 20:14:03 +0800 Subject: [PATCH 11/42] feat(unidata): more progress --- .../controller/BlockDataController.java | 127 +++++++++++++++++- .../controller/SlimefunUniversalData.java | 4 + .../migrator/BlockStorageMigrator.java | 20 ++- .../storage/util/StorageCacheUtils.java | 48 ++++--- .../listeners/BlockListener.java | 14 +- 5 files changed, 176 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index b30e72fd81..ce581734c7 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -17,6 +17,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import io.github.bakedlibs.dough.collections.Pair; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.HashMap; import java.util.HashSet; @@ -64,6 +65,13 @@ public class BlockDataController extends ADataController { lock = new ScopedLock(); } + /** + * 初始化数据控制器 + * + * @param dataAdapter 使用的 {@link IDataSourceAdapter} + * @param maxReadThread 最大数据库读线程数 + * @param maxWriteThread 最大数据库写线程数 + */ @Override public void init(IDataSourceAdapter dataAdapter, int maxReadThread, int maxWriteThread) { super.init(dataAdapter, maxReadThread, maxWriteThread); @@ -71,13 +79,21 @@ public void init(IDataSourceAdapter dataAdapter, int maxReadThread, int maxWr initLoadData(); } + /** + * 初始化加载数据 + */ private void initLoadData() { switch (chunkDataLoadMode) { case LOAD_WITH_CHUNK -> loadLoadedChunks(); case LOAD_ON_STARTUP -> loadLoadedWorlds(); } + + loadUniversalData(); // FIXME: 按需加载? } + /** + * 加载所有服务器已加载的世界中的数据 + */ private void loadLoadedWorlds() { Bukkit.getScheduler() .runTaskLater( @@ -92,6 +108,9 @@ private void loadLoadedWorlds() { 1); } + /** + * 加载所有服务器已加载的世界区块中的数据 + */ private void loadLoadedChunks() { Bukkit.getScheduler() .runTaskLater( @@ -108,6 +127,23 @@ private void loadLoadedChunks() { 1); } + /** + * 加载所有通用数据 + * + * @see SlimefunUniversalData + */ + private void loadUniversalData() { + Bukkit.getScheduler() + .runTaskLater( + Slimefun.instance(), + () -> { + initLoading = true; + // TODO + initLoading = false; + }, + 1); + } + public void initDelayedSaving(Plugin p, int delayedSecond, int forceSavePeriod) { checkDestroy(); if (delayedSecond < 1 || forceSavePeriod < 1) { @@ -147,16 +183,26 @@ public void setDelayedSavingEnable(boolean isEnable) { * * @param l slimefun block location {@link Location} * @param sfId slimefun block id {@link SlimefunItem#getId()} - * @return {@link SlimefunBlockData} + * @return {@link ASlimefunDataContainer} */ @Nonnull - public SlimefunBlockData createBlock(Location l, String sfId) { + public ASlimefunDataContainer createBlock(Location l, String sfId) { checkDestroy(); - var re = getChunkDataCache(l.getChunk(), true).createBlockData(l, sfId); - if (Slimefun.getRegistry().getTickerBlocks().contains(sfId)) { - Slimefun.getTickerTask().enableTicker(l); + var sfItem = SlimefunItem.getById(sfId); + + if (sfItem instanceof UniversalDataSupport) { + var re = createUniversalData(l, sfId); + if (Slimefun.getRegistry().getTickerBlocks().contains(sfId)) { + Slimefun.getTickerTask().enableTicker(l); + } + return re; + } else { + var re = getChunkDataCache(l.getChunk(), true).createBlockData(l, sfId); + if (Slimefun.getRegistry().getTickerBlocks().contains(sfId)) { + Slimefun.getTickerTask().enableTicker(l); + } + return re; } - return re; } @Nonnull @@ -601,6 +647,75 @@ public void loadBlockDataAsync( invokeCallback(callback, blockDataList); } + @ParametersAreNonnullByDefault + public void loadUniversalData(SlimefunUniversalData uniData) { + if (uniData.isDataLoaded()) { + return; + } + + var key = new RecordKey(DataScope.UNIVERSAL_DATA); + key.addCondition(FieldKey.UNIVERSAL_UUID, uniData.getKey()); + key.addField(FieldKey.DATA_KEY); + key.addField(FieldKey.DATA_VALUE); + + lock.lock(key); + + try { + if (uniData.isDataLoaded()) { + return; + } + + getData(key) + .forEach(recordSet -> uniData.setCacheInternal( + recordSet.get(FieldKey.DATA_KEY), + DataUtils.blockDataDebase64(recordSet.get(FieldKey.DATA_VALUE)), + false)); + + uniData.setIsDataLoaded(true); + + var menuPreset = UniversalMenuPreset.getPreset(uniData.getSfId()); + if (menuPreset != null) { + var menuKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); + menuKey.addCondition(FieldKey.UNIVERSAL_UUID, uniData.getKey()); + menuKey.addField(FieldKey.INVENTORY_SLOT); + menuKey.addField(FieldKey.INVENTORY_ITEM); + + var inv = new ItemStack[54]; + + getData(menuKey) + .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = + recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); + uniData.setUniversalMenu(new UniversalMenu(menuPreset, uniData.getUUID(), inv)); + + var content = uniData.getMenuContents(); + if (content != null) { + invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); + } + } + + var sfItem = SlimefunItem.getById(uniData.getSfId()); + if (sfItem != null + && sfItem.isTicking() + && !uniData.getLastPresent() + .getBlock() + .getType() + .equals(sfItem.getItem().getType())) { + Slimefun.getTickerTask().enableTicker(uniData.getLastPresent()); + } + } finally { + lock.unlock(key); + } + } + + @ParametersAreNonnullByDefault + public void loadUniversalDataAsync( + SlimefunUniversalData uniData, IAsyncReadCallback callback) { + scheduleReadTask(() -> { + loadUniversalData(uniData); + invokeCallback(callback, uniData); + }); + } + public SlimefunChunkData getChunkData(Chunk chunk) { checkDestroy(); loadChunk(chunk, false); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index c7f8cecc04..d8fe4dcd80 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -71,6 +71,10 @@ public void removeData(String key) { return re; } + public UUID getUUID() { + return UUID.fromString(getKey()); + } + @Override public String toString() { return "SlimefunUniversalData [sfId=" + sfId + ", isPendingRemove=" + pendingRemove + "]"; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java index 0700d6b20f..03c7e1ac77 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java @@ -2,6 +2,8 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import io.github.bakedlibs.dough.config.Config; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; @@ -12,7 +14,7 @@ import java.util.Map; import java.util.logging.Level; import lombok.Getter; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -135,18 +137,24 @@ private void migrateBlock(World world, String sfId, String locStr, String jsonSt var z = Integer.parseInt(arr[3]); var loc = new Location(world, x, y, z); - var blockData = - Slimefun.getDatabaseManager().getBlockDataController().createBlock(loc, sfId); + var sfData = Slimefun.getDatabaseManager().getBlockDataController().createBlock(loc, sfId); Map data = gson.fromJson(jsonStr, new TypeToken>() {}.getType()); for (var each : data.entrySet()) { var key = each.getKey(); if ("id".equals(key)) { continue; } - blockData.setData(key, each.getValue()); + sfData.setData(key, each.getValue()); + } + + DirtyChestMenu menu = null; + + if (sfData instanceof SlimefunBlockData blockData) { + menu = blockData.getBlockMenu(); + } else if (sfData instanceof SlimefunUniversalData uniData) { + menu = uniData.getUniversalMenu(); } - var menu = blockData.getBlockMenu(); if (menu != null) { var f = new File(invFolder, world.getName() + ";" + x + ";" + y + ";" + z + ".sfi"); if (!f.isFile()) { @@ -159,7 +167,7 @@ private void migrateBlock(World world, String sfId, String locStr, String jsonSt } } - private void migrateInv(BlockMenu menu, File f) { + private void migrateInv(DirtyChestMenu menu, File f) { var cfg = new Config(f); var preset = menu.getPreset().getPresetSlots(); for (var key : cfg.getKeys()) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 3729926482..4549160a2c 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -2,7 +2,9 @@ import com.google.common.base.Preconditions; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.HashSet; @@ -21,7 +23,7 @@ * {@link com.xzavier0722.mc.plugin.slimefun4.storage.controller.BlockDataController#getBlockData} */ public class StorageCacheUtils { - private static final Set loadingData = new HashSet<>(); + private static final Set loadingData = new HashSet<>(); @ParametersAreNonnullByDefault public static boolean hasBlock(Location l) { @@ -81,39 +83,55 @@ public static void removeData(Location loc, String key) { @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(UUID uuid) { - var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalData(uuid); + var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); if (uniData == null) { return null; } + if (!uniData.isDataLoaded()) { + requestLoad(uniData); + return null; + } + return uniData.getUniversalMenu(); } - public static void requestLoad(SlimefunBlockData blockData) { - if (blockData.isDataLoaded()) { + public static void requestLoad(ASlimefunDataContainer data) { + if (data.isDataLoaded()) { return; } - if (loadingData.contains(blockData)) { + if (loadingData.contains(data)) { return; } synchronized (loadingData) { - if (loadingData.contains(blockData)) { + if (loadingData.contains(data)) { return; } - loadingData.add(blockData); + loadingData.add(data); } - Slimefun.getDatabaseManager() - .getBlockDataController() - .loadBlockDataAsync(blockData, new IAsyncReadCallback<>() { - @Override - public void onResult(SlimefunBlockData result) { - loadingData.remove(blockData); - } - }); + if (data instanceof SlimefunBlockData blockData) { + Slimefun.getDatabaseManager() + .getBlockDataController() + .loadBlockDataAsync(blockData, new IAsyncReadCallback<>() { + @Override + public void onResult(SlimefunBlockData result) { + loadingData.remove(data); + } + }); + } else if (data instanceof SlimefunUniversalData uniData) { + Slimefun.getDatabaseManager() + .getBlockDataController() + .loadUniversalDataAsync(uniData, new IAsyncReadCallback<>() { + @Override + public void onResult(SlimefunUniversalData result) { + loadingData.remove(data); + } + }); + } } public static void executeAfterLoad(SlimefunBlockData data, Runnable execute, boolean runOnMainThread) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 65c5a6d30e..f71542ea9d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -10,7 +10,6 @@ import io.github.thebusybiscuit.slimefun4.api.events.SlimefunBlockPlaceEvent; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; -import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotCardinallyRotatable; import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotRotatable; @@ -144,15 +143,10 @@ public void onBlockPlace(BlockPlaceEvent e) { var placeEvent = new SlimefunBlockPlaceEvent(e.getPlayer(), item, e.getBlock(), sfItem); Bukkit.getPluginManager().callEvent(placeEvent); - if (sfItem instanceof UniversalDataSupport) { - Slimefun.getDatabaseManager() - .getBlockDataController() - .createUniversalData(e.getBlock().getLocation(), sfItem.getId()); - } else { - Slimefun.getDatabaseManager() - .getBlockDataController() - .createBlock(e.getBlock().getLocation(), sfItem.getId()); - } + Slimefun.getDatabaseManager() + .getBlockDataController() + .createBlock(e.getBlock().getLocation(), sfItem.getId()); + sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); } } From ddf3093ca7ea6fae19ff1888a1aa05d79e74cacc Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 2 Apr 2024 19:45:05 +0800 Subject: [PATCH 12/42] feat(unidata): complete create/remove unidata --- .../slimefun4/storage/common/RecordSet.java | 6 + .../controller/BlockDataController.java | 116 ++++++++++++++---- 2 files changed, 100 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java index 3c67ffb70d..fad59fd8af 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import javax.annotation.ParametersAreNonnullByDefault; import org.bukkit.inventory.ItemStack; @@ -56,6 +57,11 @@ public ItemStack getItemStack(FieldKey key) { return DataUtils.string2ItemStack(data.get(key)); } + @ParametersAreNonnullByDefault + public UUID getUUID(FieldKey key) { + return UUID.fromString(data.get(key)); + } + public boolean getBoolean(FieldKey key) { return getInt(key) == 1; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index ce581734c7..612dfb8036 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -43,17 +44,55 @@ import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitTask; +/** + * 方块数据控制器 + *

+ * 用于管理区块中的 Slimefun 方块数据 + *

+ * {@link SlimefunBlockData} + * {@link SlimefunUniversalData} + * + * @author Xzavier0722 + * @author NoRainCity + */ public class BlockDataController extends ADataController { - + /** + * 延迟写数据任务队列 + */ private final Map delayedWriteTasks; + /** + * 区块数据缓存 + */ private final Map loadedChunk; + /** + * 通用数据缓存 + */ private final Map loadedUniversalData; + /** + * 方块物品栏快照 + */ private final Map>> invSnapshots; + /** + * 全局控制器加载数据锁 + * + * {@link ScopedLock} + */ private final ScopedLock lock; + /** + * 延时加载模式标志 + */ private boolean enableDelayedSaving = false; + private int delayedSecond = 0; private BukkitTask looperTask; + /** + * 区块数据加载模式 + * {@link ChunkDataLoadMode} + */ private ChunkDataLoadMode chunkDataLoadMode; + /** + * 初始化加载中标志 + */ private boolean initLoading = false; BlockDataController() { @@ -87,8 +126,6 @@ private void initLoadData() { case LOAD_WITH_CHUNK -> loadLoadedChunks(); case LOAD_ON_STARTUP -> loadLoadedWorlds(); } - - loadUniversalData(); // FIXME: 按需加载? } /** @@ -128,26 +165,16 @@ private void loadLoadedChunks() { } /** - * 加载所有通用数据 + * 初始化延时加载任务 * - * @see SlimefunUniversalData + * @param p 插件实例 + * @param delayedSecond 首次执行延时 + * @param forceSavePeriod 强制保存周期 */ - private void loadUniversalData() { - Bukkit.getScheduler() - .runTaskLater( - Slimefun.instance(), - () -> { - initLoading = true; - // TODO - initLoading = false; - }, - 1); - } - public void initDelayedSaving(Plugin p, int delayedSecond, int forceSavePeriod) { checkDestroy(); if (delayedSecond < 1 || forceSavePeriod < 1) { - throw new IllegalArgumentException("Second must be greater than 0!"); + throw new IllegalArgumentException("save period second must be greater than 0!"); } enableDelayedSaving = true; this.delayedSecond = delayedSecond; @@ -179,11 +206,13 @@ public void setDelayedSavingEnable(boolean isEnable) { } /** - * Creates a new slimefun block data at specific location + * 在指定位置新建方块 * - * @param l slimefun block location {@link Location} - * @param sfId slimefun block id {@link SlimefunItem#getId()} - * @return {@link ASlimefunDataContainer} + * @param l Slimefun 方块位置 {@link Location} + * @param sfId Slimefun 物品 ID {@link SlimefunItem#getId()} + * @return 方块数据, 可能会返回两类数据 + * {@link SlimefunBlockData} + * {@link SlimefunUniversalData} */ @Nonnull public ASlimefunDataContainer createBlock(Location l, String sfId) { @@ -270,6 +299,8 @@ public void removeBlock(Location l) { var removed = getChunkDataCache(l.getChunk(), true).removeBlockData(l); if (removed == null) { + getUniversalDataFromCache(l).ifPresent(data -> removeUniversalData(data.getUUID())); + return; } @@ -423,6 +454,19 @@ public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback getUniversalDataFromCache(@Nonnull Location l) { + checkDestroy(); + + return loadedUniversalData.values().stream() + .filter(uniData -> uniData.getLastPresent().equals(l)) + .findFirst(); + } + /** * Move block data to specific location *

@@ -515,6 +559,8 @@ public void loadChunk(Chunk chunk, boolean isNewChunk) { loadChunkData(chunkData); + // 按区块加载方块数据 + var key = new RecordKey(DataScope.BLOCK_RECORD); key.addField(FieldKey.LOCATION); key.addField(FieldKey.SLIMEFUN_ID); @@ -536,6 +582,32 @@ public void loadChunk(Chunk chunk, boolean isNewChunk) { scheduleReadTask(() -> loadBlockData(blockData)); } }); + + // 按区块对应世界加载通用数据 + + var uniKey = new RecordKey(DataScope.UNIVERSAL_RECORD); + uniKey.addField(FieldKey.LAST_PRESENT); + // FIXME: 不应该在区块加载中再直接加载全世界 + uniKey.addCondition(FieldKey.LAST_PRESENT, chunk.getWorld().getName() + ";%"); + getData(uniKey, true).forEach(data -> { + var sfId = data.get(FieldKey.SLIMEFUN_ID); + var sfItem = SlimefunItem.getById(sfId); + + if (sfItem == null) { + return; + } + + var uuid = data.getUUID(FieldKey.UNIVERSAL_UUID); + var location = LocationUtils.toLocation(data.get(FieldKey.LAST_PRESENT)); + + var cache = getUniversalDataFromCache(uuid); + var uniData = cache == null ? new SlimefunUniversalData(uuid, location, sfId) : cache; + + if (sfItem.loadDataByDefault()) { + scheduleReadTask(() -> loadUniversalData(uniData)); + } + }); + Bukkit.getPluginManager().callEvent(new SlimefunChunkDataLoadEvent(chunkData)); } From 4af94d2f4f611f0232747da198b8d10bd953c4fa Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 2 Apr 2024 20:24:39 +0800 Subject: [PATCH 13/42] feat(unidata): use pdc to identify uni container --- .../storage/util/StorageCacheUtils.java | 13 +++++ .../core/services/BlockDataService.java | 47 ++++++++++++++++++- .../listeners/BlockListener.java | 29 +++++++++--- .../SlimefunItemInteractListener.java | 11 ++++- 4 files changed, 89 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 4549160a2c..2872e44aec 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -15,6 +15,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Location; +import org.bukkit.block.Block; /** * Utils to access the cached block data. @@ -30,6 +31,11 @@ public static boolean hasBlock(Location l) { return getBlock(l) != null; } + @ParametersAreNonnullByDefault + public static boolean hasUniversalBlock(Location l) { + return Slimefun.getBlockDataService().getUniversalDataUUID(l.getBlock()).isPresent(); + } + @ParametersAreNonnullByDefault @Nullable public static SlimefunBlockData getBlock(Location l) { return Slimefun.getDatabaseManager().getBlockDataController().getBlockDataFromCache(l); @@ -81,6 +87,13 @@ public static void removeData(Location loc, String key) { return blockData.getBlockMenu(); } + @ParametersAreNonnullByDefault + @Nullable public static UniversalMenu getUniversalMenu(Block block) { + var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); + + return uuid.map(StorageCacheUtils::getUniversalMenu).orElse(null); + } + @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(UUID uuid) { var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java index f2bde71bb3..992d82adbd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java @@ -4,6 +4,7 @@ import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import io.papermc.lib.PaperLib; import java.util.Optional; +import java.util.UUID; import java.util.logging.Level; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -32,6 +33,7 @@ public class BlockDataService implements Keyed { private final NamespacedKey namespacedKey; + private final NamespacedKey universalDataKey; /** * This creates a new {@link BlockDataService} for the given {@link Plugin}. @@ -45,6 +47,7 @@ public class BlockDataService implements Keyed { */ public BlockDataService(@Nonnull Plugin plugin, @Nonnull String key) { namespacedKey = new NamespacedKey(plugin, key); + universalDataKey = new NamespacedKey(plugin, "slimefun_unidata_uuid"); } @Override @@ -61,6 +64,30 @@ public NamespacedKey getKey() { * The value to store */ public void setBlockData(@Nonnull Block b, @Nonnull String value) { + setBlockData(b, namespacedKey, value); + } + + /** + * This will store the universal data {@link UUID} inside the NBT data of the given {@link Block} + * + * @param b + * The {@link Block} in which to store the given value + * @param uuid + * The uuid linked to certain slimefun item + */ + public void setUniversalDataUUID(@Nonnull Block b, @Nonnull String uuid) { + setBlockData(b, namespacedKey, uuid); + } + + /** + * This will store the given {@link String} inside the NBT data of the given {@link Block} + * + * @param b + * The {@link Block} in which to store the given value + * @param value + * The value to store + */ + public void setBlockData(@Nonnull Block b, @Nonnull NamespacedKey key, @Nonnull String value) { Validate.notNull(b, "The block cannot be null!"); Validate.notNull(value, "The value cannot be null!"); @@ -73,7 +100,7 @@ public void setBlockData(@Nonnull Block b, @Nonnull String value) { if (state instanceof TileState tileState) { try { PersistentDataContainer container = tileState.getPersistentDataContainer(); - container.set(namespacedKey, PersistentDataType.STRING, value); + container.set(key, PersistentDataType.STRING, value); state.update(); } catch (Exception x) { Slimefun.logger().log(Level.SEVERE, "Please check if your Server Software is up to date!"); @@ -102,13 +129,29 @@ public void setBlockData(@Nonnull Block b, @Nonnull String value) { * @return The stored value */ public Optional getBlockData(@Nonnull Block b) { + return getBlockData(b, namespacedKey); + } + + public Optional getUniversalDataUUID(@Nonnull Block b) { + var uuid = getBlockData(b, universalDataKey); + + return uuid.map(data -> { + try { + return UUID.fromString(data); + } catch (IllegalArgumentException e) { + return null; + } + }); + } + + public Optional getBlockData(@Nonnull Block b, @Nonnull NamespacedKey key) { Validate.notNull(b, "The block cannot be null!"); BlockState state = PaperLib.getBlockState(b, false).getState(); PersistentDataContainer container = getPersistentDataContainer(state); if (container != null) { - return Optional.ofNullable(container.get(namespacedKey, PersistentDataType.STRING)); + return Optional.ofNullable(container.get(key, PersistentDataType.STRING)); } else { return Optional.empty(); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index f71542ea9d..07e51ee395 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -2,6 +2,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.protection.Interaction; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; @@ -119,7 +120,8 @@ public void onBlockPlace(BlockPlaceEvent e) { if (!sfItem.canUse(e.getPlayer(), true)) { e.setCancelled(true); } else { - if (e.getBlock().getBlockData() instanceof Rotatable rotatable + var block = e.getBlock(); + if (block.getBlockData() instanceof Rotatable rotatable && !(rotatable.getRotation() == BlockFace.UP || rotatable.getRotation() == BlockFace.DOWN)) { BlockFace rotation = null; @@ -137,17 +139,30 @@ public void onBlockPlace(BlockPlaceEvent e) { if (rotation != null) { rotatable.setRotation(rotation); - e.getBlock().setBlockData(rotatable); + block.setBlockData(rotatable); } } - var placeEvent = new SlimefunBlockPlaceEvent(e.getPlayer(), item, e.getBlock(), sfItem); + var placeEvent = new SlimefunBlockPlaceEvent(e.getPlayer(), item, block, sfItem); Bukkit.getPluginManager().callEvent(placeEvent); - Slimefun.getDatabaseManager() - .getBlockDataController() - .createBlock(e.getBlock().getLocation(), sfItem.getId()); + if (placeEvent.isCancelled()) { + e.setCancelled(true); + } else { + if (Slimefun.getBlockDataService().isTileEntity(block.getType())) { + Slimefun.getBlockDataService().setBlockData(block, sfItem.getId()); + } + + var data = Slimefun.getDatabaseManager() + .getBlockDataController() + .createBlock(block.getLocation(), sfItem.getId()); - sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); + if (Slimefun.getBlockDataService().isTileEntity(block.getType()) + && data instanceof SlimefunUniversalData) { + Slimefun.getBlockDataService().setUniversalDataUUID(block, data.getKey()); + } + + sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); + } } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index f861c070e3..9dc99b87f1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -13,8 +13,8 @@ import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; +import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; @@ -58,6 +58,7 @@ public void onRightClick(PlayerInteractEvent e) { // We especially don't want to open inventories as that can cause duplication if (e.getClickedBlock() != null && StorageCacheUtils.hasBlock(e.getClickedBlock().getLocation()) + && StorageCacheUtils.hasUniversalBlock(e.getClickedBlock().getLocation()) && StorageCacheUtils.getBlock(e.getClickedBlock().getLocation()) .isPendingRemove()) { e.setCancelled(true); @@ -148,6 +149,12 @@ private void openInventory(Player p, SlimefunItem item, Block clickedBlock, Play var blockData = StorageCacheUtils.getBlock(clickedBlock.getLocation()); if (blockData == null) { + var uniMenu = StorageCacheUtils.getUniversalMenu(clickedBlock); + + if (uniMenu != null) { + openMenu(uniMenu, clickedBlock, p); + } + return; } @@ -178,7 +185,7 @@ public void onResult(SlimefunBlockData result) { } } - private void openMenu(BlockMenu menu, Block b, Player p) { + private void openMenu(DirtyChestMenu menu, Block b, Player p) { if (menu != null) { if (menu.canOpen(b, p)) { menu.open(p); From 3d4cdb9903ca8b07ab45768044ce62ca24a72dc4 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 2 Apr 2024 20:51:57 +0800 Subject: [PATCH 14/42] feat(unidata): update unidata `lastPresent` --- .../plugin/slimefun4/storage/util/StorageCacheUtils.java | 6 ++++-- .../items/androids/ProgrammableAndroid.java | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 2872e44aec..30f1debdf9 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -91,11 +91,11 @@ public static void removeData(Location loc, String key) { @Nullable public static UniversalMenu getUniversalMenu(Block block) { var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); - return uuid.map(StorageCacheUtils::getUniversalMenu).orElse(null); + return uuid.map(uniId -> getUniversalMenu(uniId, block.getLocation())).orElse(null); } @ParametersAreNonnullByDefault - @Nullable public static UniversalMenu getUniversalMenu(UUID uuid) { + @Nullable public static UniversalMenu getUniversalMenu(UUID uuid, Location l) { var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); if (uniData == null) { @@ -107,6 +107,8 @@ public static void removeData(Location loc, String key) { return null; } + uniData.setLastPresent(l); + return uniData.getUniversalMenu(); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 7b5cd89fa0..488501668d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -309,7 +309,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(0, (pl, slot, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -344,7 +344,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(slot, (pl, s, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -633,7 +633,7 @@ public void openScriptEditor(Player p, Block b) { menu.addItem(8, new CustomItemStack(HeadTexture.SCRIPT_LEFT.getAsItemStack(), "&6> 返回", "", "&7返回机器人控制面板")); menu.addMenuClickHandler(8, (pl, slot, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -1009,7 +1009,7 @@ public void addItems(Block b, ItemStack... items) { Validate.notNull(b, "The Block cannot be null."); UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); if (inv != null) { for (ItemStack item : items) { From 05e01511ad95f1ee8955112742a90bfab037d5e6 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 7 Apr 2024 09:28:10 +0800 Subject: [PATCH 15/42] fix(android): use unidata on move --- .../storage/util/StorageCacheUtils.java | 23 ++++++ .../items/androids/ProgrammableAndroid.java | 75 +++++++++++-------- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 30f1debdf9..2a44dee684 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -87,6 +87,29 @@ public static void removeData(Location loc, String key) { return blockData.getBlockMenu(); } + @ParametersAreNonnullByDefault + @Nullable public static SlimefunUniversalData getUniversalData(UUID uuid, Location l) { + var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); + + if (uniData == null) { + return null; + } + + if (!uniData.isDataLoaded()) { + requestLoad(uniData); + return null; + } + + return uniData; + } + + @ParametersAreNonnullByDefault + @Nullable public static SlimefunUniversalData getUniversalData(Block block) { + var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); + + return uuid.map(uniId -> getUniversalData(uniId, block.getLocation())).orElse(null); + } + @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(Block block) { var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 488501668d..35c35558a4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -85,7 +85,6 @@ public class ProgrammableAndroid extends SlimefunItem private static final int MAX_SCRIPT_LENGTH = 54; private static final NamespacedKey OWNER_KEY = new NamespacedKey(Slimefun.instance(), "android_owner"); - private static final NamespacedKey UUID_KEY = new NamespacedKey(Slimefun.instance(), "android_uuid"); private static final NamespacedKey SCRIPT_KEY = new NamespacedKey(Slimefun.instance(), "android_script"); private static final NamespacedKey SCRIPT_INDEX_KEY = new NamespacedKey(Slimefun.instance(), "android_script_step"); private static final NamespacedKey FUEL_KEY = new NamespacedKey(Slimefun.instance(), "android_fuel"); @@ -194,7 +193,6 @@ public void onPlayerPlace(BlockPlaceEvent e) { UUID uuid = UUID.randomUUID(); PDCUtil.setValue(b, PDCUtil.UUID_TYPE, OWNER_KEY, p.getUniqueId()); - PDCUtil.setValue(b, PDCUtil.UUID_TYPE, UUID_KEY, uuid); PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); PDCUtil.setValue(b, PersistentDataType.SHORT, SCRIPT_INDEX_KEY, (short) 0); PDCUtil.setValue(b, PersistentDataType.INTEGER, FUEL_KEY, 0); @@ -221,8 +219,8 @@ private BlockBreakHandler onBreak() { @Override public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List drops) { Block b = e.getBlock(); + Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); UUID owner = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, OWNER_KEY); - UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); if (!e.getPlayer().hasPermission("slimefun.android.bypass") && !e.getPlayer().getUniqueId().equals(owner)) { @@ -231,16 +229,19 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro return; } - var uniData = - Slimefun.getDatabaseManager().getBlockDataController().getUniversalData(uuid); + uuid.ifPresent(data -> { + var uniData = Slimefun.getDatabaseManager() + .getBlockDataController() + .getUniversalData(data); - if (uniData != null) { - var menu = uniData.getUniversalMenu(); - if (menu != null) { - menu.dropItems(b.getLocation(), 43); - menu.dropItems(b.getLocation(), getOutputSlots()); + if (uniData != null) { + var menu = uniData.getUniversalMenu(); + if (menu != null) { + menu.dropItems(b.getLocation(), 43); + menu.dropItems(b.getLocation(), getOutputSlots()); + } } - } + }); } }; } @@ -295,9 +296,9 @@ public void openScript(Player p, Block b, String sourceCode) { ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); - UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); + Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); - if (uuid == null) { + if (uuid.isEmpty()) { throw new IllegalStateException("Android missing uuid"); } @@ -309,7 +310,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(0, (pl, slot, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -322,6 +323,7 @@ public void openScript(Player p, Block b, String sourceCode) { String[] script = CommonPatterns.DASH.split(sourceCode); for (int i = 1; i < script.length; i++) { + int index = i; if (i == script.length - 1) { @@ -344,7 +346,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(slot, (pl, s, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -590,7 +592,11 @@ public void openScriptEditor(Player p, Block b) { new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); - UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); + Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); + + if (uuid.isEmpty()) { + throw new IllegalStateException("Android missing uuid"); + } menu.addItem(1, new CustomItemStack(HeadTexture.SCRIPT_FORWARD.getAsItemStack(), "&2> 编辑脚本", "", "&a修改你现有的脚本")); menu.addMenuClickHandler(1, (pl, slot, item, action) -> { @@ -633,7 +639,7 @@ public void openScriptEditor(Player p, Block b) { menu.addItem(8, new CustomItemStack(HeadTexture.SCRIPT_LEFT.getAsItemStack(), "&6> 返回", "", "&7返回机器人控制面板")); menu.addMenuClickHandler(8, (pl, slot, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -1008,8 +1014,13 @@ public boolean onClick( public void addItems(Block b, ItemStack... items) { Validate.notNull(b, "The Block cannot be null."); - UUID uuid = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, UUID_KEY); - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid, b.getLocation()); + Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); + + if (uuid.isEmpty()) { + throw new IllegalStateException("Android missing uuid"); + } + + UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); if (inv != null) { for (ItemStack item : items) { @@ -1019,23 +1030,23 @@ public void addItems(Block b, ItemStack... items) { } @ParametersAreNonnullByDefault - protected void move(Block b, BlockFace face, Block block) { - var blockData = StorageCacheUtils.getBlock(b.getLocation()); - OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(blockData.getData("owner"))); + protected void move(Block from, BlockFace face, Block to) { + var uniData = StorageCacheUtils.getUniversalData(from); + OfflinePlayer owner = Bukkit.getOfflinePlayer(PDCUtil.getValue(from, PDCUtil.UUID_TYPE, OWNER_KEY)); - if (!Slimefun.getProtectionManager().hasPermission(owner, block.getLocation(), Interaction.PLACE_BLOCK)) { + if (!Slimefun.getProtectionManager().hasPermission(owner, to.getLocation(), Interaction.PLACE_BLOCK)) { return; } - if (block.getY() > block.getWorld().getMinHeight() - && block.getY() < block.getWorld().getMaxHeight() - && block.isEmpty()) { + if (to.getY() > to.getWorld().getMinHeight() + && to.getY() < to.getWorld().getMaxHeight() + && to.isEmpty()) { - if (!block.getWorld().getWorldBorder().isInside(block.getLocation())) { + if (!to.getWorld().getWorldBorder().isInside(to.getLocation())) { return; } - block.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { + to.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { if (data instanceof Rotatable rotatable) { rotatable.setRotation(face.getOppositeFace()); } @@ -1043,15 +1054,15 @@ protected void move(Block b, BlockFace face, Block block) { Slimefun.runSync(() -> { PlayerSkin skin = PlayerSkin.fromBase64(texture); - Material type = block.getType(); + Material type = to.getType(); // Ensure that this Block is still a Player Head if (type == Material.PLAYER_HEAD || type == Material.PLAYER_WALL_HEAD) { - PlayerHead.setSkin(block, skin, true); + PlayerHead.setSkin(to, skin, true); } }); - b.setType(Material.AIR); - Slimefun.getDatabaseManager().getBlockDataController().setBlockDataLocation(blockData, block.getLocation()); + from.setType(Material.AIR); + uniData.setLastPresent(to.getLocation()); } } From 1185b0ee3ffdb7dcc3e5c0b0bd38f8afb7568648 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 27 Apr 2024 10:53:03 +0800 Subject: [PATCH 16/42] chore: sync up --- .../items/androids/ProgrammableAndroid.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 35c35558a4..b76f39a2ce 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -2,6 +2,7 @@ import city.norain.slimefun4.utils.PDCUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.chat.ChatInput; import io.github.bakedlibs.dough.common.ChatColors; @@ -32,6 +33,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.UUID; import java.util.function.Predicate; @@ -127,20 +129,25 @@ public boolean canOpen(Block b, Player p) { @Override public void newInstance(UniversalMenu menu, Block b) { + var uniData = StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation()); + + Objects.requireNonNull( + uniData, + "Unable to get android's universal data at " + LocationUtils.locationToString(b.getLocation()) + + "!"); + menu.replaceExistingItem( 15, new CustomItemStack(HeadTexture.SCRIPT_START.getAsItemStack(), "&a启动/继续运行")); menu.addMenuClickHandler(15, (p, slot, item, action) -> { Slimefun.getLocalization().sendMessage(p, "android.started", true); - PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, true); - // StorageCacheUtils.setData(b.getLocation(), "paused", "false"); + uniData.setData("paused", "false"); p.closeInventory(); return false; }); menu.replaceExistingItem(17, new CustomItemStack(HeadTexture.SCRIPT_PAUSE.getAsItemStack(), "&4暂停运行")); menu.addMenuClickHandler(17, (p, slot, item, action) -> { - PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); - // StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + uniData.setData("paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); return false; }); @@ -150,8 +157,7 @@ public void newInstance(UniversalMenu menu, Block b) { new CustomItemStack( HeadTexture.ENERGY_REGULATOR.getAsItemStack(), "&b内存核心", "", "&8\u21E8 &7单击打开脚本编辑器")); menu.addMenuClickHandler(16, (p, slot, item, action) -> { - PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); - // StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + uniData.setData("paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); openScriptEditor(p, b); return false; @@ -165,8 +171,7 @@ public void newInstance(UniversalMenu menu, Block b) { "", Slimefun.getLocalization().getMessage("android.access-manager.subtitle"))); menu.addMenuClickHandler(25, (p, slot, item, action) -> { - PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, false); - // StorageCacheUtils.setData(b.getLocation(), "paused", "true"); + uniData.setData("paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); AndroidShareMenu.openShareMenu(p, b); return false; @@ -190,7 +195,6 @@ private BlockPlaceHandler onPlace() { public void onPlayerPlace(BlockPlaceEvent e) { Player p = e.getPlayer(); Block b = e.getBlock(); - UUID uuid = UUID.randomUUID(); PDCUtil.setValue(b, PDCUtil.UUID_TYPE, OWNER_KEY, p.getUniqueId()); PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); @@ -1032,6 +1036,12 @@ public void addItems(Block b, ItemStack... items) { @ParametersAreNonnullByDefault protected void move(Block from, BlockFace face, Block to) { var uniData = StorageCacheUtils.getUniversalData(from); + + if (uniData == null) { + throw new IllegalStateException("This android doesn't have universal data! Location at " + + LocationUtils.locationToString(from.getLocation())); + } + OfflinePlayer owner = Bukkit.getOfflinePlayer(PDCUtil.getValue(from, PDCUtil.UUID_TYPE, OWNER_KEY)); if (!Slimefun.getProtectionManager().hasPermission(owner, to.getLocation(), Interaction.PLACE_BLOCK)) { From 406fdff54af8e5e7ca92be78fc45aba8df281a66 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 28 May 2024 20:23:06 +0800 Subject: [PATCH 17/42] feat(sql): refine unidata table creation --- .../storage/adapter/mysql/MysqlAdapter.java | 82 +++++++++++++++---- .../adapter/postgresql/PostgreSqlAdapter.java | 1 + .../adapter/sqlcommon/SqlCommonAdapter.java | 2 + .../storage/adapter/sqlite/SqliteAdapter.java | 46 +++++++++++ 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java index cf84f4c6a6..5631007713 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java @@ -9,6 +9,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; @@ -127,6 +128,8 @@ private void createBlockStorageTables() { createBlockInvTable(); createChunkDataTable(); createUniversalInventoryTable(); + createUniversalRecordTable(); + createUniversalDataTable(); } private void createProfileTable() { @@ -289,24 +292,6 @@ private void createChunkDataTable() { + ");"); } - private void createUniversalInventoryTable() { - executeSql("CREATE TABLE IF NOT EXISTS " - + universalInvTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " TEXT NOT NULL," - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");"); - } - private void createBlockInvTable() { executeSql("CREATE TABLE IF NOT EXISTS " + blockInvTable @@ -333,4 +318,65 @@ private void createBlockInvTable() { + ")" + ");"); } + + private void createUniversalInventoryTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalInvTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " CHAR(64) NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); + } + + private void createUniversalRecordTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_SLIMEFUN_ID + + " CHAR(64) NOT NULL, " + + FIELD_LAST_PRESENT + + " CHAR(64) NOT NULL, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ")" + + ");"); + } + + private void createUniversalDataTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalDataTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_UNIVERSAL_UUID + + ") " + + "REFERENCES " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); + } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index 25be59456d..10fc4664d6 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -141,6 +141,7 @@ private void createBlockStorageTables() { createChunkDataTable(); createUniversalInventoryTable(); createUniversalRecordTable(); + createUniversalDataTable(); } private void createProfileTable() { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java index 53638ac88e..01574f435d 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlCommonAdapter.java @@ -83,5 +83,7 @@ public void shutdown() { chunkDataTable = null; blockInvTable = null; universalInvTable = null; + universalDataTable = null; + universalRecordTable = null; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index e30f702710..a1d14bc57e 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -9,6 +9,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; @@ -118,6 +119,8 @@ private void createBlockStorageTables() { createBlockInvTable(); createChunkDataTable(); createUniversalInventoryTable(); + createUniversalRecordTable(); + createUniversalDataTable(); } private void createProfileTable() { @@ -331,6 +334,49 @@ private void createUniversalInventoryTable() { + ");"); } + private void createUniversalRecordTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_SLIMEFUN_ID + + " CHAR(64) NOT NULL, " + + FIELD_LAST_PRESENT + + " CHAR(64) NOT NULL, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ")" + + ");"); + } + + private void createUniversalDataTable() { + executeSql("CREATE TABLE IF NOT EXISTS " + + universalDataTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_UNIVERSAL_UUID + + ") " + + "REFERENCES " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); + } + public synchronized void executeSql(String sql) { super.executeSql(sql); } From 789191d4a7f871ab3acc787019a4fa6edcccd752 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 6 Jul 2024 03:54:09 +0800 Subject: [PATCH 18/42] feat: rewrite ticker to tick universal ticker --- .../storage/adapter/mysql/MysqlAdapter.java | 98 +++++++++---------- .../adapter/postgresql/PostgreSqlAdapter.java | 2 + .../storage/adapter/sqlite/SqliteAdapter.java | 70 ++++++------- .../storage/controller/ADataContainer.java | 82 ++++++++++++++++ .../controller/ASlimefunDataContainer.java | 87 +++------------- .../storage/controller/SlimefunBlockData.java | 22 +---- .../storage/controller/SlimefunChunkData.java | 2 +- .../controller/SlimefunUniversalData.java | 11 +-- .../storage/util/StorageCacheUtils.java | 6 +- .../items/androids/AndroidAction.java | 4 +- .../items/androids/Instruction.java | 4 +- .../items/androids/ProgrammableAndroid.java | 32 +++--- .../implementation/tasks/TickerTask.java | 31 +++++- .../Objects/handlers/BlockTicker.java | 27 +++++ 14 files changed, 268 insertions(+), 210 deletions(-) create mode 100644 src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataContainer.java diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java index 5631007713..c3aa958840 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java @@ -321,62 +321,62 @@ private void createBlockInvTable() { private void createUniversalInventoryTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalInvTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_INVENTORY_SLOT - + " TINYINT UNSIGNED NOT NULL, " - + FIELD_INVENTORY_ITEM - + " CHAR(64) NOT NULL," - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_INVENTORY_SLOT - + ")" - + ");"); + + universalInvTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_INVENTORY_SLOT + + " TINYINT UNSIGNED NOT NULL, " + + FIELD_INVENTORY_ITEM + + " CHAR(64) NOT NULL," + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_INVENTORY_SLOT + + ")" + + ");"); } private void createUniversalRecordTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalRecordTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_SLIMEFUN_ID - + " CHAR(64) NOT NULL, " - + FIELD_LAST_PRESENT - + " CHAR(64) NOT NULL, " - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ")" - + ");"); + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_SLIMEFUN_ID + + " CHAR(64) NOT NULL, " + + FIELD_LAST_PRESENT + + " CHAR(64) NOT NULL, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ")" + + ");"); } private void createUniversalDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalDataTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_DATA_KEY - + " CHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_UNIVERSAL_UUID - + ") " - + "REFERENCES " - + universalRecordTable - + "(" - + FIELD_UNIVERSAL_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + universalDataTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_UNIVERSAL_UUID + + ") " + + "REFERENCES " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index 10fc4664d6..577e3a388d 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -44,6 +44,8 @@ public void initStorage(DataType type) { blockInvTable = SqlUtils.mapTable(DataScope.BLOCK_INVENTORY, config.tablePrefix()); chunkDataTable = SqlUtils.mapTable(DataScope.CHUNK_DATA, config.tablePrefix()); universalInvTable = SqlUtils.mapTable(DataScope.UNIVERSAL_INVENTORY, config.tablePrefix()); + universalDataTable = SqlUtils.mapTable(DataScope.UNIVERSAL_DATA, config.tablePrefix()); + universalRecordTable = SqlUtils.mapTable(DataScope.UNIVERSAL_RECORD, config.tablePrefix()); createBlockStorageTables(); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index 86b337b21e..527938625e 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -338,45 +338,45 @@ private void createUniversalInventoryTable() { private void createUniversalRecordTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalRecordTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_SLIMEFUN_ID - + " CHAR(64) NOT NULL, " - + FIELD_LAST_PRESENT - + " CHAR(64) NOT NULL, " - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ")" - + ");"); + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_SLIMEFUN_ID + + " CHAR(64) NOT NULL, " + + FIELD_LAST_PRESENT + + " CHAR(64) NOT NULL, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ")" + + ");"); } private void createUniversalDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalDataTable - + "(" - + FIELD_UNIVERSAL_UUID - + " CHAR(64) NOT NULL, " - + FIELD_DATA_KEY - + " CHAR(64) NOT NULL, " - + FIELD_DATA_VALUE - + " TEXT NOT NULL, " - + "FOREIGN KEY (" - + FIELD_UNIVERSAL_UUID - + ") " - + "REFERENCES " - + universalRecordTable - + "(" - + FIELD_UNIVERSAL_UUID - + ") " - + "ON UPDATE CASCADE ON DELETE CASCADE, " - + "PRIMARY KEY (" - + FIELD_UNIVERSAL_UUID - + ", " - + FIELD_DATA_KEY - + ")" - + ");"); + + universalDataTable + + "(" + + FIELD_UNIVERSAL_UUID + + " CHAR(64) NOT NULL, " + + FIELD_DATA_KEY + + " CHAR(64) NOT NULL, " + + FIELD_DATA_VALUE + + " TEXT NOT NULL, " + + "FOREIGN KEY (" + + FIELD_UNIVERSAL_UUID + + ") " + + "REFERENCES " + + universalRecordTable + + "(" + + FIELD_UNIVERSAL_UUID + + ") " + + "ON UPDATE CASCADE ON DELETE CASCADE, " + + "PRIMARY KEY (" + + FIELD_UNIVERSAL_UUID + + ", " + + FIELD_DATA_KEY + + ")" + + ");"); } public synchronized void executeSql(String sql) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataContainer.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataContainer.java new file mode 100644 index 0000000000..3787d07152 --- /dev/null +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ADataContainer.java @@ -0,0 +1,82 @@ +package com.xzavier0722.mc.plugin.slimefun4.storage.controller; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +public abstract class ADataContainer { + private final String key; + private final Map data; + private volatile boolean isDataLoaded = false; + + @ParametersAreNonnullByDefault + public ADataContainer(String key) { + this.key = key; + data = new ConcurrentHashMap<>(); + } + + @ParametersAreNonnullByDefault + public ADataContainer(String key, ADataContainer other) { + this.key = key; + this.data = other.data; + this.isDataLoaded = other.isDataLoaded; + } + + public boolean isDataLoaded() { + return isDataLoaded; + } + + protected String getCacheInternal(String key) { + return data.get(key); + } + + protected void setIsDataLoaded(boolean isDataLoaded) { + this.isDataLoaded = isDataLoaded; + } + + protected void setCacheInternal(String key, String val, boolean override) { + if (override) { + data.put(key, val); + } else { + data.putIfAbsent(key, val); + } + } + + protected String removeCacheInternal(String key) { + return data.remove(key); + } + + protected void checkData() { + if (!isDataLoaded) { + throw new IllegalStateException("Unable to access unloaded data!"); + } + } + + @Nonnull + public Map getAllData() { + checkData(); + return Collections.unmodifiableMap(data); + } + + @Nonnull + public Set getDataKeys() { + checkData(); + return Collections.unmodifiableSet(data.keySet()); + } + + @Nullable public String getData(String key) { + checkData(); + return getCacheInternal(key); + } + + @Nonnull + public String getKey() { + return key; + } + + public abstract void setData(String key, String val); +} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java index e7a6f84a69..2faba0b9de 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java @@ -1,82 +1,23 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; +import lombok.Getter; +import lombok.Setter; -public abstract class ASlimefunDataContainer { - private final String key; - private final Map data; - private volatile boolean isDataLoaded = false; +public abstract class ASlimefunDataContainer extends ADataContainer { + @Getter + private final String sfId; - @ParametersAreNonnullByDefault - public ASlimefunDataContainer(String key) { - this.key = key; - data = new ConcurrentHashMap<>(); - } - - @ParametersAreNonnullByDefault - public ASlimefunDataContainer(String key, ASlimefunDataContainer other) { - this.key = key; - this.data = other.data; - this.isDataLoaded = other.isDataLoaded; - } - - public boolean isDataLoaded() { - return isDataLoaded; - } - - protected String getCacheInternal(String key) { - return data.get(key); - } - - protected void setIsDataLoaded(boolean isDataLoaded) { - this.isDataLoaded = isDataLoaded; - } - - protected void setCacheInternal(String key, String val, boolean override) { - if (override) { - data.put(key, val); - } else { - data.putIfAbsent(key, val); - } - } - - protected String removeCacheInternal(String key) { - return data.remove(key); - } - - protected void checkData() { - if (!isDataLoaded) { - throw new IllegalStateException("Unable to access unloaded data!"); - } - } + @Setter + @Getter + private volatile boolean pendingRemove = false; - @Nonnull - public Map getAllData() { - checkData(); - return Collections.unmodifiableMap(data); + public ASlimefunDataContainer(String key, String sfId) { + super(key); + this.sfId = sfId; } - @Nonnull - public Set getDataKeys() { - checkData(); - return Collections.unmodifiableSet(data.keySet()); + public ASlimefunDataContainer(String key, ADataContainer other, String sfId) { + super(key, other); + this.sfId = sfId; } - - @Nullable public String getData(String key) { - checkData(); - return getCacheInternal(key); - } - - @Nonnull - public String getKey() { - return key; - } - - public abstract void setData(String key, String val); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java index 833a17e69c..417f669903 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java @@ -12,22 +12,18 @@ public class SlimefunBlockData extends ASlimefunDataContainer { private final Location location; - private final String sfId; private volatile BlockMenu menu; - private volatile boolean pendingRemove = false; @ParametersAreNonnullByDefault SlimefunBlockData(Location location, String sfId) { - super(LocationUtils.getLocKey(location)); + super(LocationUtils.getLocKey(location), sfId); this.location = location; - this.sfId = sfId; } @ParametersAreNonnullByDefault SlimefunBlockData(Location location, SlimefunBlockData other) { - super(LocationUtils.getLocKey(location), other); + super(LocationUtils.getLocKey(location), other, other.getSfId()); this.location = location; - this.sfId = other.sfId; } @Nonnull @@ -37,7 +33,7 @@ public Location getLocation() { @Nonnull public String getSfId() { - return sfId; + return super.getSfId(); } @ParametersAreNonnullByDefault @@ -80,22 +76,14 @@ void setBlockMenu(BlockMenu blockMenu) { return re; } - public void setPendingRemove(boolean pendingRemove) { - this.pendingRemove = pendingRemove; - } - - public boolean isPendingRemove() { - return pendingRemove; - } - @Override public String toString() { return "SlimefunBlockData [sfId=" - + sfId + + getSfId() + ", location=" + location + ", isPendingRemove=" - + pendingRemove + + isPendingRemove() + "]"; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java index 9dadc5afd0..174b150a8f 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunChunkData.java @@ -15,7 +15,7 @@ import org.bukkit.Chunk; import org.bukkit.Location; -public class SlimefunChunkData extends ASlimefunDataContainer { +public class SlimefunChunkData extends ADataContainer { private static final SlimefunBlockData INVALID_BLOCK_DATA = new SlimefunBlockData( new Location(Bukkit.getWorlds().get(0), Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), "INVALID_BLOCK_DATA_SF_KEY"); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index d8fe4dcd80..6ea4c8f727 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -11,9 +11,6 @@ import org.bukkit.inventory.ItemStack; public class SlimefunUniversalData extends ASlimefunDataContainer { - @Getter - private final String sfId; - @Setter @Getter private volatile UniversalMenu universalMenu; @@ -28,16 +25,14 @@ public class SlimefunUniversalData extends ASlimefunDataContainer { @ParametersAreNonnullByDefault SlimefunUniversalData(UUID uuid, Location location, String sfId) { - super(uuid.toString()); + super(uuid.toString(), sfId); this.lastPresent = location; - this.sfId = sfId; } @ParametersAreNonnullByDefault SlimefunUniversalData(UUID uuid, Location location, SlimefunUniversalData other) { - super(uuid.toString(), other); + super(uuid.toString(), other, other.getSfId()); this.lastPresent = location; - this.sfId = other.sfId; } @ParametersAreNonnullByDefault @@ -77,6 +72,6 @@ public UUID getUUID() { @Override public String toString() { - return "SlimefunUniversalData [sfId=" + sfId + ", isPendingRemove=" + pendingRemove + "]"; + return "SlimefunUniversalData [sfId=" + getSfId() + ", isPendingRemove=" + pendingRemove + "]"; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 2a44dee684..3925372509 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -2,7 +2,7 @@ import com.google.common.base.Preconditions; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; -import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ADataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -24,7 +24,7 @@ * {@link com.xzavier0722.mc.plugin.slimefun4.storage.controller.BlockDataController#getBlockData} */ public class StorageCacheUtils { - private static final Set loadingData = new HashSet<>(); + private static final Set loadingData = new HashSet<>(); @ParametersAreNonnullByDefault public static boolean hasBlock(Location l) { @@ -135,7 +135,7 @@ public static void removeData(Location loc, String key) { return uniData.getUniversalMenu(); } - public static void requestLoad(ASlimefunDataContainer data) { + public static void requestLoad(ADataContainer data) { if (data.isDataLoaded()) { return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java index a7aea4acb5..ff004a57ec 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java @@ -1,11 +1,11 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @FunctionalInterface interface AndroidAction { - void perform(ProgrammableAndroid android, Block b, BlockMenu inventory, BlockFace face); + void perform(ProgrammableAndroid android, Block b, UniversalMenu inventory, BlockFace face); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java index 5a611ccfa6..da37c669e2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java @@ -8,7 +8,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.block.Block; @@ -277,7 +277,7 @@ public AndroidType getRequiredType() { } @ParametersAreNonnullByDefault - public void execute(ProgrammableAndroid android, Block b, BlockMenu inventory, BlockFace face) { + public void execute(ProgrammableAndroid android, Block b, UniversalMenu inventory, BlockFace face) { Validate.notNull(method, "Instruction '" + name() + "' must be executed manually!"); method.perform(android, b, inventory, face); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index b76f39a2ce..c560ff980d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -1,7 +1,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; import city.norain.slimefun4.utils.PDCUtil; -import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.chat.ChatInput; @@ -46,8 +46,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenuPreset; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; @@ -282,7 +280,7 @@ public void preRegister() { addItemHandler(new BlockTicker() { @Override - public void tick(Block b, SlimefunItem item, SlimefunBlockData data) { + public void tick(Block b, SlimefunItem item, SlimefunUniversalData data) { if (b != null && data != null) { ProgrammableAndroid.this.tick(b, data); } @@ -807,14 +805,14 @@ public int getTier() { return tier; } - protected void tick(Block b, SlimefunBlockData data) { + protected void tick(Block b, SlimefunUniversalData data) { if (b.getType() != Material.PLAYER_HEAD) { // The Android was destroyed or moved. return; } if ("false".equals(data.getData("paused"))) { - BlockMenu menu = data.getBlockMenu(); + UniversalMenu menu = data.getUniversalMenu(); String fuelData = data.getData("fuel"); float fuel = fuelData == null ? 0 : Float.parseFloat(fuelData); @@ -855,7 +853,7 @@ protected void tick(Block b, SlimefunBlockData data) { @ParametersAreNonnullByDefault private void executeInstruction( - Instruction instruction, Block b, BlockMenu inv, SlimefunBlockData data, int index) { + Instruction instruction, Block b, UniversalMenu inv, SlimefunUniversalData data, int index) { if ("true".equals(data.getData("paused"))) { return; } @@ -908,7 +906,7 @@ protected void rotate(Block b, BlockFace current, int mod) { StorageCacheUtils.setData(b.getLocation(), "rotation", rotation.name()); } - protected void depositItems(BlockMenu menu, Block facedBlock) { + protected void depositItems(UniversalMenu menu, Block facedBlock) { if (facedBlock.getType() == Material.DISPENSER && StorageCacheUtils.isBlock(facedBlock.getLocation(), "ANDROID_INTERFACE_ITEMS")) { BlockState state = PaperLib.getBlockState(facedBlock, false).getState(); @@ -932,7 +930,7 @@ protected void depositItems(BlockMenu menu, Block facedBlock) { } } - protected void refuel(BlockMenu menu, Block facedBlock) { + protected void refuel(UniversalMenu menu, Block facedBlock) { if (facedBlock.getType() == Material.DISPENSER && StorageCacheUtils.isBlock(facedBlock.getLocation(), "ANDROID_INTERFACE_FUEL")) { BlockState state = PaperLib.getBlockState(facedBlock, false).getState(); @@ -950,7 +948,7 @@ protected void refuel(BlockMenu menu, Block facedBlock) { } private boolean insertFuel( - BlockMenu menu, Inventory dispenser, int slot, ItemStack currentFuel, ItemStack newFuel) { + UniversalMenu menu, Inventory dispenser, int slot, ItemStack currentFuel, ItemStack newFuel) { if (currentFuel == null) { menu.replaceExistingItem(43, newFuel); dispenser.setItem(slot, null); @@ -971,7 +969,7 @@ private boolean insertFuel( } @ParametersAreNonnullByDefault - private void consumeFuel(Block b, BlockMenu menu) { + private void consumeFuel(Block b, UniversalMenu menu) { ItemStack item = menu.getItemInSlot(43); if (item != null && item.getType() != Material.AIR) { @@ -991,7 +989,7 @@ private void consumeFuel(Block b, BlockMenu menu) { } } - private void constructMenu(@Nonnull BlockMenuPreset preset) { + private void constructMenu(@Nonnull UniversalMenuPreset preset) { preset.drawBackground(BORDER); preset.drawBackground(ChestMenuUtils.getOutputSlotTexture(), OUTPUT_BORDER); @@ -1080,23 +1078,23 @@ protected void attack(Block b, BlockFace face, Predicate predicate throw new UnsupportedOperationException("Non-butcher Android tried to butcher!"); } - protected void fish(Block b, BlockMenu menu) { + protected void fish(Block b, UniversalMenu menu) { throw new UnsupportedOperationException("Non-fishing Android tried to fish!"); } - protected void dig(Block b, BlockMenu menu, Block block) { + protected void dig(Block b, UniversalMenu menu, Block block) { throw new UnsupportedOperationException("Non-mining Android tried to mine!"); } - protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) { + protected void moveAndDig(Block b, UniversalMenu menu, BlockFace face, Block block) { throw new UnsupportedOperationException("Non-mining Android tried to mine!"); } - protected boolean chopTree(Block b, BlockMenu menu, BlockFace face) { + protected boolean chopTree(Block b, UniversalMenu menu, BlockFace face) { throw new UnsupportedOperationException("Non-woodcutter Android tried to chop a Tree!"); } - protected void farm(Block b, BlockMenu menu, Block block, boolean isAdvanced) { + protected void farm(Block b, UniversalMenu menu, Block block, boolean isAdvanced) { throw new UnsupportedOperationException("Non-farming Android tried to farm!"); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index 76589bba84..a8add8ff55 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -1,6 +1,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.tasks; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.bakedlibs.dough.blocks.ChunkPosition; @@ -133,10 +136,13 @@ private void tickChunk(ChunkPosition chunk, Set tickers, Set tickers, @Nonnull Location l) { - var blockData = StorageCacheUtils.getBlock(l); + var blockData = StorageCacheUtils.hasBlock(l) + ? StorageCacheUtils.getBlock(l) + : StorageCacheUtils.getUniversalData(l.getBlock()); if (blockData == null || !blockData.isDataLoaded() || blockData.isPendingRemove()) { return; } + SlimefunItem item = SlimefunItem.getById(blockData.getSfId()); if (item != null && item.getBlockTicker() != null) { @@ -175,9 +181,28 @@ private void tickLocation(@Nonnull Set tickers, @Nonnull Location l } @ParametersAreNonnullByDefault - private void tickBlock(Location l, Block b, SlimefunItem item, SlimefunBlockData data, long timestamp) { + private void tickBlock(Location l, Block b, SlimefunItem item, ASlimefunDataContainer data, long timestamp) { try { - item.getBlockTicker().tick(b, item, data); + switch (data) { + case SlimefunBlockData blockData -> { + if (item.getBlockTicker().isUniversal()) { + Slimefun.logger() + .log(Level.WARNING, "BlockTicker is universal even identified as non-universal!"); + return; + } + item.getBlockTicker().tick(b, item, blockData); + } + case SlimefunUniversalData universalData -> { + if (!item.getBlockTicker().isUniversal()) { + Slimefun.logger() + .log(Level.WARNING, "BlockTicker is non-universal even identified as universal!"); + return; + } + item.getBlockTicker().tick(b, item, universalData); + } + default -> throw new IllegalStateException( + "Unable to tick abnormal blockdata @" + LocationUtils.locationToString(l)); + } } catch (Exception | LinkageError x) { reportErrors(l, item, x); } finally { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/Objects/handlers/BlockTicker.java b/src/main/java/me/mrCookieSlime/Slimefun/Objects/handlers/BlockTicker.java index b72020f1a0..fdb1c9eb2a 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/Objects/handlers/BlockTicker.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/Objects/handlers/BlockTicker.java @@ -2,18 +2,31 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.controller.BlockDataConfigWrapper; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import io.github.thebusybiscuit.slimefun4.api.exceptions.IncompatibleItemHandlerException; import io.github.thebusybiscuit.slimefun4.api.items.ItemHandler; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; import java.util.Optional; +import lombok.Getter; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import org.bukkit.block.Block; public abstract class BlockTicker implements ItemHandler { + @Getter + private final boolean universal; + protected boolean unique = true; + public BlockTicker() { + this.universal = false; + } + + public BlockTicker(boolean universal) { + this.universal = universal; + } + public void update() { if (unique) { uniqueTick(); @@ -58,6 +71,20 @@ public void tick(Block b, SlimefunItem item, SlimefunBlockData data) { tick(b, item, new BlockDataConfigWrapper(data)); } + /** + * This method is called every tick for every block + * + * @param b + * The {@link Block} that was ticked + * @param item + * The corresponding {@link SlimefunItem} + * @param data + * The data stored in this {@link Block} + */ + public void tick(Block b, SlimefunItem item, SlimefunUniversalData data) { + // Override this method and fill it with content + } + @Deprecated public void tick(Block b, SlimefunItem item, Config data) {} From 9f7717218900de9c74cd20a627645b9f2c640a2e Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 6 Jul 2024 04:03:35 +0800 Subject: [PATCH 19/42] refactor: enforce material check for universal item --- .../slimefun4/core/attributes/UniversalDataSupport.java | 6 ++++++ .../slimefun4/core/services/BlockDataService.java | 2 +- .../slimefun4/implementation/listeners/BlockListener.java | 6 ++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java index bf9cee8b5a..57b4c32d86 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java @@ -7,6 +7,12 @@ * This attribute represents {@link SlimefunItem} support store * {@link SlimefunUniversalData} * + * The {@link SlimefunItem} to be universal MUST be able to use PDC. + * Otherwise, it will lose its uuid to identify. + * + * Check here to find out what type of block can support this: + * Paper Doc + * * @author NoRainCity * * @see SlimefunUniversalData diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java index 992d82adbd..6b4fbfedff 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java @@ -76,7 +76,7 @@ public void setBlockData(@Nonnull Block b, @Nonnull String value) { * The uuid linked to certain slimefun item */ public void setUniversalDataUUID(@Nonnull Block b, @Nonnull String uuid) { - setBlockData(b, namespacedKey, uuid); + setBlockData(b, universalDataKey, uuid); } /** diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 57c2750dfb..7f35917313 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -158,9 +158,11 @@ public void onBlockPlace(BlockPlaceEvent e) { .getBlockDataController() .createBlock(block.getLocation(), sfItem.getId()); - if (Slimefun.getBlockDataService().isTileEntity(block.getType()) - && data instanceof SlimefunUniversalData) { + if (data instanceof SlimefunUniversalData + && Slimefun.getBlockDataService().isTileEntity(block.getType())) { Slimefun.getBlockDataService().setUniversalDataUUID(block, data.getKey()); + } else { + throw new IllegalStateException("You must use pdc support material for this Slimefun item!"); } sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); From 96a8480f9fe7b88a4e830c761138ca5d32aa94fa Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Tue, 16 Jul 2024 13:57:13 +0800 Subject: [PATCH 20/42] fix: remove pattern matching from java 21 --- .../storage/util/StorageCacheUtils.java | 6 ++++ .../items/androids/FarmerAndroid.java | 9 +++--- .../items/androids/FishermanAndroid.java | 4 +-- .../items/androids/MinerAndroid.java | 16 +++++------ .../items/androids/WoodcutterAndroid.java | 10 +++---- .../implementation/tasks/TickerTask.java | 28 ++++++++----------- .../api/inventory/UniversalMenuPreset.java | 4 +-- 7 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 3925372509..dd2a7e63bf 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -59,6 +59,12 @@ public static boolean isBlock(Location l, String id) { return blockData == null ? null : blockData.getData(key); } + @ParametersAreNonnullByDefault + @Nullable public static String getUniversalData(UUID uuid, Location loc, String key) { + var universalData = getUniversalData(uuid, loc); + return universalData == null ? null : universalData.getData(key); + } + @ParametersAreNonnullByDefault public static void setData(Location loc, String key, String val) { var block = getBlock(loc); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java index ec94ac2dc0..b552f5410a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java @@ -11,7 +11,7 @@ import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -35,10 +35,9 @@ public AndroidType getAndroidType() { } @Override - protected void farm(Block b, BlockMenu menu, Block block, boolean isAdvanced) { - - OfflinePlayer owner = - Bukkit.getOfflinePlayer(UUID.fromString(StorageCacheUtils.getData(b.getLocation(), "owner"))); + protected void farm(Block b, UniversalMenu menu, Block block, boolean isAdvanced) { + OfflinePlayer owner = Bukkit.getOfflinePlayer( + UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); if (!Slimefun.getProtectionManager().hasPermission(owner, block, Interaction.BREAK_BLOCK)) { return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java index 6ea86da447..4eae2ccab4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java @@ -7,7 +7,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; import java.util.concurrent.ThreadLocalRandom; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; @@ -50,7 +50,7 @@ public AndroidType getAndroidType() { } @Override - protected void fish(Block b, BlockMenu menu) { + protected void fish(Block b, UniversalMenu menu) { Block water = b.getRelative(BlockFace.DOWN); if (water.getType() == Material.WATER) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index b0319b96b8..a8d9a8fc9c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -16,8 +16,8 @@ import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.BlockStorage; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -71,12 +71,12 @@ public AndroidType getAndroidType() { @Override @ParametersAreNonnullByDefault - protected void dig(Block b, BlockMenu menu, Block block) { + protected void dig(Block b, UniversalMenu menu, Block block) { Collection drops = block.getDrops(effectivePickaxe); if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) { - OfflinePlayer owner = - Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))); + OfflinePlayer owner = Bukkit.getOfflinePlayer( + UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); if (Slimefun.getProtectionManager().hasPermission(owner, block.getLocation(), Interaction.BREAK_BLOCK)) { AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); @@ -96,12 +96,12 @@ protected void dig(Block b, BlockMenu menu, Block block) { @Override @ParametersAreNonnullByDefault - protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) { + protected void moveAndDig(Block b, UniversalMenu menu, BlockFace face, Block block) { Collection drops = block.getDrops(effectivePickaxe); if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) { - OfflinePlayer owner = - Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))); + OfflinePlayer owner = Bukkit.getOfflinePlayer( + UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); if (Slimefun.getProtectionManager().hasPermission(owner, block.getLocation(), Interaction.BREAK_BLOCK)) { AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); @@ -125,7 +125,7 @@ protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) } @ParametersAreNonnullByDefault - private void breakBlock(BlockMenu menu, Collection drops, Block block) { + private void breakBlock(UniversalMenu menu, Collection drops, Block block) { if (!block.getWorld().getWorldBorder().isInside(block.getLocation())) { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java index aa8600d7fd..4c601e0d6c 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java @@ -14,7 +14,7 @@ import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -40,7 +40,7 @@ public AndroidType getAndroidType() { } @Override - protected boolean chopTree(Block b, BlockMenu menu, BlockFace face) { + protected boolean chopTree(Block b, UniversalMenu menu, BlockFace face) { Block target = b.getRelative(face); if (!target.getWorld().getWorldBorder().isInside(target.getLocation())) { @@ -54,8 +54,8 @@ protected boolean chopTree(Block b, BlockMenu menu, BlockFace face) { Block log = list.get(list.size() - 1); log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType()); - OfflinePlayer owner = - Bukkit.getOfflinePlayer(UUID.fromString(StorageCacheUtils.getData(b.getLocation(), "owner"))); + OfflinePlayer owner = Bukkit.getOfflinePlayer( + UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); if (Slimefun.getProtectionManager().hasPermission(owner, log.getLocation(), Interaction.BREAK_BLOCK)) { breakLog(log, b, menu, face); } @@ -68,7 +68,7 @@ protected boolean chopTree(Block b, BlockMenu menu, BlockFace face) { } @ParametersAreNonnullByDefault - private void breakLog(Block log, Block android, BlockMenu menu, BlockFace face) { + private void breakLog(Block log, Block android, UniversalMenu menu, BlockFace face) { ItemStack drop = new ItemStack(log.getType()); // We try to push the log into the android's inventory, but nothing happens if it does not fit diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index a8add8ff55..d27989e426 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -183,24 +183,20 @@ private void tickLocation(@Nonnull Set tickers, @Nonnull Location l @ParametersAreNonnullByDefault private void tickBlock(Location l, Block b, SlimefunItem item, ASlimefunDataContainer data, long timestamp) { try { - switch (data) { - case SlimefunBlockData blockData -> { - if (item.getBlockTicker().isUniversal()) { - Slimefun.logger() - .log(Level.WARNING, "BlockTicker is universal even identified as non-universal!"); - return; - } - item.getBlockTicker().tick(b, item, blockData); + if (data instanceof SlimefunBlockData blockData) { + if (item.getBlockTicker().isUniversal()) { + Slimefun.logger().log(Level.WARNING, "BlockTicker is universal even identified as non-universal!"); + return; } - case SlimefunUniversalData universalData -> { - if (!item.getBlockTicker().isUniversal()) { - Slimefun.logger() - .log(Level.WARNING, "BlockTicker is non-universal even identified as universal!"); - return; - } - item.getBlockTicker().tick(b, item, universalData); + item.getBlockTicker().tick(b, item, blockData); + } else if (data instanceof SlimefunUniversalData universalData) { + if (!item.getBlockTicker().isUniversal()) { + Slimefun.logger().log(Level.WARNING, "BlockTicker is non-universal even identified as universal!"); + return; } - default -> throw new IllegalStateException( + item.getBlockTicker().tick(b, item, universalData); + } else { + throw new IllegalStateException( "Unable to tick abnormal blockdata @" + LocationUtils.locationToString(l)); } } catch (Exception | LinkageError x) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java index b5a9814b82..9ec4b8a2f1 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -27,8 +27,8 @@ protected void clone(@Nonnull UniversalMenu menu, @Nonnull Block b) { menu.addItem(slot, getItemInSlot(slot)); } - if (size > -1) { - menu.addItem(size - 1, null); + if (getSize() > -1) { + menu.addItem(getSize() - 1, null); } newInstance(menu, b); From b950cbe7998e78ebd51f084e6376ea526aef9a50 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 21 Jul 2024 15:34:35 +0800 Subject: [PATCH 21/42] fix(sqlite): missing actual table name sqlite side --- .../slimefun4/storage/adapter/sqlite/SqliteAdapter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index 527938625e..178371afcb 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -338,7 +338,7 @@ private void createUniversalInventoryTable() { private void createUniversalRecordTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalRecordTable + + SqlUtils.mapTable(DataScope.UNIVERSAL_RECORD) + "(" + FIELD_UNIVERSAL_UUID + " CHAR(64) NOT NULL, " @@ -354,7 +354,7 @@ private void createUniversalRecordTable() { private void createUniversalDataTable() { executeSql("CREATE TABLE IF NOT EXISTS " - + universalDataTable + + SqlUtils.mapTable(DataScope.UNIVERSAL_DATA) + "(" + FIELD_UNIVERSAL_UUID + " CHAR(64) NOT NULL, " From 7580a41a54194dd4d1ca3762bb42b4a42d62d1bb Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 21 Jul 2024 15:43:20 +0800 Subject: [PATCH 22/42] fix(sqlite): missing actual table name sqlite side --- .../plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java | 2 +- .../plugin/slimefun4/storage/controller/ControllerHolder.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index 178371afcb..ccefb9cf30 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -366,7 +366,7 @@ private void createUniversalDataTable() { + FIELD_UNIVERSAL_UUID + ") " + "REFERENCES " - + universalRecordTable + + SqlUtils.mapTable(DataScope.UNIVERSAL_RECORD) + "(" + FIELD_UNIVERSAL_UUID + ") " diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ControllerHolder.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ControllerHolder.java index 763c9aabc1..544d4f6627 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ControllerHolder.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ControllerHolder.java @@ -9,7 +9,8 @@ public class ControllerHolder { private final Map controllers; public static CT getController(Class clazz, StorageType type) { - return ((ControllerHolder) holders.get(clazz)).get(type); + final var holder = holders.get(clazz); + return holder == null ? null : ((ControllerHolder) holder).get(type); } public static void clearControllers() { From a8f41aca654193beb955a5db5b09efa8af1e6556 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 21 Jul 2024 17:28:41 +0800 Subject: [PATCH 23/42] fix(unidata): fix broken universal data system --- .../storage/adapter/sqlcommon/SqlUtils.java | 2 + .../controller/BlockDataController.java | 25 +++- .../storage/util/StorageCacheUtils.java | 24 +++- .../core/attributes/UniversalDataSupport.java | 2 +- .../items/androids/ProgrammableAndroid.java | 75 +++++----- .../listeners/DebugFishListener.java | 10 -- .../implementation/tasks/TickerTask.java | 130 +++++++++++++++--- 7 files changed, 191 insertions(+), 77 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java index a15975794e..fd7bb83e44 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java @@ -9,6 +9,7 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; @@ -63,6 +64,7 @@ public class SqlUtils { fieldMap.put(FieldKey.DATA_KEY, FIELD_DATA_KEY); fieldMap.put(FieldKey.DATA_VALUE, FIELD_DATA_VALUE); fieldMap.put(FieldKey.UNIVERSAL_UUID, FIELD_UNIVERSAL_UUID); + fieldMap.put(FieldKey.LAST_PRESENT, FIELD_LAST_PRESENT); mapper = new FieldMapper<>(fieldMap); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 7bf655ea3b..372073bfa6 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -250,7 +250,7 @@ public SlimefunUniversalData createUniversalData(Location l, String sfId) { uniData.setUniversalMenu(new UniversalMenu(preset, uuid)); } - Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uuid, sfId); + Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uuid, sfId, l); return uniData; } @@ -277,12 +277,13 @@ void saveNewBlock(Location l, String sfId) { * @param uuid universal data uuid * @param sfId the item universal data represents */ - void saveUniversalData(UUID uuid, String sfId) { + void saveUniversalData(UUID uuid, String sfId, Location l) { var key = new RecordKey(DataScope.UNIVERSAL_RECORD); var data = new RecordSet(); data.put(FieldKey.UNIVERSAL_UUID, uuid.toString()); data.put(FieldKey.SLIMEFUN_ID, sfId); + data.put(FieldKey.LAST_PRESENT, LocationUtils.getLocKey(l)); var scopeKey = new UUIDKey(DataScope.NONE, uuid); removeDelayedBlockDataUpdates(scopeKey); // Shouldn't have.. But for safe.. @@ -331,14 +332,18 @@ public void removeUniversalData(UUID uuid) { return; } + toRemove.setPendingRemove(true); + var menu = toRemove.getUniversalMenu(); if (menu != null) { InventoryUtil.closeInventory(menu.toInventory()); } if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { - Slimefun.getTickerTask().disableTicker(toRemove.getLastPresent()); + Slimefun.getTickerTask().disableTicker(uuid); } + + removeUniversalBlockDirectly(uuid); } void removeBlockDirectly(Location l) { @@ -351,6 +356,16 @@ void removeBlockDirectly(Location l) { scheduleDeleteTask(scopeKey, key, true); } + void removeUniversalBlockDirectly(UUID uuid) { + checkDestroy(); + var scopeKey = new UUIDKey(DataScope.NONE, uuid); + removeDelayedBlockDataUpdates(scopeKey); + + var key = new RecordKey(DataScope.UNIVERSAL_RECORD); + key.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); + scheduleDeleteTask(scopeKey, key, true); + } + /** * Get slimefun block data at specific location * @@ -772,7 +787,7 @@ public void loadUniversalData(SlimefunUniversalData uniData) { .getBlock() .getType() .equals(sfItem.getItem().getType())) { - Slimefun.getTickerTask().enableTicker(uniData.getLastPresent()); + Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); } } finally { lock.unlock(key); @@ -1024,7 +1039,7 @@ void scheduleDelayedBlockDataUpdate(SlimefunBlockData blockData, String key) { void scheduleDelayedUniversalDataUpdate(SlimefunUniversalData universalData, String key) { var scopeKey = new UUIDKey(DataScope.NONE, universalData.getKey()); - var reqKey = new RecordKey(DataScope.UNIVERSAL_RECORD); + var reqKey = new RecordKey(DataScope.UNIVERSAL_DATA); reqKey.addCondition(FieldKey.UNIVERSAL_UUID, universalData.getKey()); reqKey.addCondition(FieldKey.DATA_KEY, key); if (enableDelayedSaving) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index dd2a7e63bf..1872d130d9 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -109,6 +109,14 @@ public static void removeData(Location loc, String key) { return uniData; } + /** + * Get universal data from block + *

+ * You **must** call this method from sync! + * + * @param block {@link Block} + * @return {@link SlimefunUniversalData} + */ @ParametersAreNonnullByDefault @Nullable public static SlimefunUniversalData getUniversalData(Block block) { var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); @@ -116,11 +124,23 @@ public static void removeData(Location loc, String key) { return uuid.map(uniId -> getUniversalData(uniId, block.getLocation())).orElse(null); } + /** + * Get universal menu from block + *

+ * You **must** call this method from sync! + * + * @param block {@link Block} + * @return {@link SlimefunUniversalData} + */ @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(Block block) { - var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); + var uniData = getUniversalData(block); + + if (uniData == null) { + return null; + } - return uuid.map(uniId -> getUniversalMenu(uniId, block.getLocation())).orElse(null); + return uniData.getUniversalMenu(); } @ParametersAreNonnullByDefault diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java index 57b4c32d86..3489f74cb8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java @@ -7,7 +7,7 @@ * This attribute represents {@link SlimefunItem} support store * {@link SlimefunUniversalData} * - * The {@link SlimefunItem} to be universal MUST be able to use PDC. + * The {@link SlimefunItem} to be universal is encouraged be able to use PDC. * Otherwise, it will lose its uuid to identify. * * Check here to find out what type of block can support this: diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index c560ff980d..ff16bcde45 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -1,6 +1,5 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; -import city.norain.slimefun4.utils.PDCUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; @@ -54,7 +53,6 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.OfflinePlayer; import org.bukkit.Tag; import org.bukkit.block.Block; @@ -70,7 +68,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataType; public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, RecipeDisplayItem, NotDiagonallyRotatable, UniversalDataSupport { @@ -84,13 +81,6 @@ public class ProgrammableAndroid extends SlimefunItem private static final String DEFAULT_SCRIPT = "START-TURN_LEFT-REPEAT"; private static final int MAX_SCRIPT_LENGTH = 54; - private static final NamespacedKey OWNER_KEY = new NamespacedKey(Slimefun.instance(), "android_owner"); - private static final NamespacedKey SCRIPT_KEY = new NamespacedKey(Slimefun.instance(), "android_script"); - private static final NamespacedKey SCRIPT_INDEX_KEY = new NamespacedKey(Slimefun.instance(), "android_script_step"); - private static final NamespacedKey FUEL_KEY = new NamespacedKey(Slimefun.instance(), "android_fuel"); - private static final NamespacedKey ROTATION_KEY = new NamespacedKey(Slimefun.instance(), "android_rotation"); - private static final NamespacedKey STATUS_KEY = new NamespacedKey(Slimefun.instance(), "android_status"); - protected final List fuelTypes = new ArrayList<>(); protected final String texture; private final int tier; @@ -113,7 +103,14 @@ public void init() { @Override public boolean canOpen(Block b, Player p) { - UUID owner = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, OWNER_KEY); + var uniData = StorageCacheUtils.getUniversalData(b); + + Objects.requireNonNull( + uniData, + "Unable to get android's universal data at " + LocationUtils.locationToString(b.getLocation()) + + "!"); + + UUID owner = UUID.fromString(uniData.getData("owner")); boolean isOwner = p.getUniqueId().equals(owner) || p.hasPermission("slimefun.android.bypass"); @@ -194,16 +191,15 @@ public void onPlayerPlace(BlockPlaceEvent e) { Player p = e.getPlayer(); Block b = e.getBlock(); - PDCUtil.setValue(b, PDCUtil.UUID_TYPE, OWNER_KEY, p.getUniqueId()); - PDCUtil.setValue(b, PersistentDataType.STRING, SCRIPT_KEY, DEFAULT_SCRIPT); - PDCUtil.setValue(b, PersistentDataType.SHORT, SCRIPT_INDEX_KEY, (short) 0); - PDCUtil.setValue(b, PersistentDataType.INTEGER, FUEL_KEY, 0); - PDCUtil.setValue( - b, - PersistentDataType.STRING, - ROTATION_KEY, - p.getFacing().getOppositeFace().toString()); - PDCUtil.setValue(b, PersistentDataType.BOOLEAN, STATUS_KEY, true); + var universalData = StorageCacheUtils.getUniversalData(b); + + universalData.setData("owner", p.getUniqueId().toString()); + universalData.setData("script", DEFAULT_SCRIPT); + universalData.setData("index", String.valueOf(0)); + universalData.setData("fuel", String.valueOf(0)); + universalData.setData( + "rotation", p.getFacing().getOppositeFace().toString()); + universalData.setData("paused", String.valueOf(true)); b.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { if (data instanceof Rotatable rotatable) { @@ -222,28 +218,29 @@ private BlockBreakHandler onBreak() { public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List drops) { Block b = e.getBlock(); Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); - UUID owner = PDCUtil.getValue(b, PDCUtil.UUID_TYPE, OWNER_KEY); - if (!e.getPlayer().hasPermission("slimefun.android.bypass") - && !e.getPlayer().getUniqueId().equals(owner)) { - // The Player is not allowed to break this android - e.setCancelled(true); - return; + if (uuid.isEmpty()) { + throw new IllegalStateException( + "Missing universal id android @" + LocationUtils.locationToString(b.getLocation())); } - uuid.ifPresent(data -> { - var uniData = Slimefun.getDatabaseManager() - .getBlockDataController() - .getUniversalData(data); + var uniData = + Slimefun.getDatabaseManager().getBlockDataController().getUniversalData(uuid.get()); - if (uniData != null) { - var menu = uniData.getUniversalMenu(); - if (menu != null) { - menu.dropItems(b.getLocation(), 43); - menu.dropItems(b.getLocation(), getOutputSlots()); - } + if (uniData != null) { + if (!e.getPlayer().hasPermission("slimefun.android.bypass") + && !e.getPlayer().getUniqueId().equals(uniData.getData("owner"))) { + // The Player is not allowed to break this android + e.setCancelled(true); + return; } - }); + + var menu = uniData.getUniversalMenu(); + if (menu != null) { + menu.dropItems(b.getLocation(), 43); + menu.dropItems(b.getLocation(), getOutputSlots()); + } + } } }; } @@ -1040,7 +1037,7 @@ protected void move(Block from, BlockFace face, Block to) { + LocationUtils.locationToString(from.getLocation())); } - OfflinePlayer owner = Bukkit.getOfflinePlayer(PDCUtil.getValue(from, PDCUtil.UUID_TYPE, OWNER_KEY)); + OfflinePlayer owner = Bukkit.getOfflinePlayer(uniData.getData("owner")); if (!Slimefun.getProtectionManager().hasPermission(owner, to.getLocation(), Interaction.PLACE_BLOCK)) { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index 965f1d85c9..f2feed1933 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -192,16 +192,6 @@ private void sendInfo(Player p, Block b) { p.sendMessage(ChatColors.color("&dTicker: " + redCross)); } - var ticker = Slimefun.getTickerTask().getLocations(b.getChunk()).stream() - .filter(l -> l.equals(b.getLocation())) - .findFirst(); - - if (ticker.isPresent()) { - p.sendMessage(ChatColors.color("&dTicking: " + greenCheckmark)); - } else { - p.sendMessage(ChatColors.color("&dTicking: " + redCross)); - } - if (Slimefun.getProfiler().hasTimings(b)) { p.sendMessage( ChatColors.color(" &dTimings: &e" + Slimefun.getProfiler().getTime(b))); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index d27989e426..a3296040dc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import javax.annotation.Nonnull; @@ -22,7 +23,6 @@ import org.apache.commons.lang.Validate; import org.bukkit.Chunk; import org.bukkit.Location; -import org.bukkit.block.Block; import org.bukkit.scheduler.BukkitScheduler; /** @@ -41,6 +41,11 @@ public class TickerTask implements Runnable { */ private final Map> tickingLocations = new ConcurrentHashMap<>(); + /** + * This Map holds all locations of currently actively ticking universal items. + */ + private final Map tickingUniversalLocations = new ConcurrentHashMap<>(); + /** * This Map tracks how many bugs have occurred in a given Location . * If too many bugs happen, we delete that Location. @@ -100,6 +105,16 @@ public void run() { for (Map.Entry> entry : loc) { tickChunk(entry.getKey(), tickers, new HashSet<>(entry.getValue())); } + + Set> uniLoc; + + synchronized (tickingUniversalLocations) { + uniLoc = new HashSet<>(tickingUniversalLocations.entrySet()); + } + + for (Map.Entry entry : uniLoc) { + tickUniversalLocation(entry.getKey(), entry.getValue(), tickers); + } } // Start a new tick cycle for every BlockTicker @@ -136,9 +151,7 @@ private void tickChunk(ChunkPosition chunk, Set tickers, Set tickers, @Nonnull Location l) { - var blockData = StorageCacheUtils.hasBlock(l) - ? StorageCacheUtils.getBlock(l) - : StorageCacheUtils.getUniversalData(l.getBlock()); + var blockData = StorageCacheUtils.getBlock(l); if (blockData == null || !blockData.isDataLoaded() || blockData.isPendingRemove()) { return; } @@ -163,14 +176,50 @@ private void tickLocation(@Nonnull Set tickers, @Nonnull Location l if (blockData.isPendingRemove()) { return; } - Block b = l.getBlock(); - tickBlock(l, b, item, blockData, System.nanoTime()); + tickBlock(l, item, blockData, System.nanoTime()); + }); + } else { + long timestamp = Slimefun.getProfiler().newEntry(); + item.getBlockTicker().update(); + tickBlock(l, item, blockData, timestamp); + } + + tickers.add(item.getBlockTicker()); + } catch (Exception x) { + reportErrors(l, item, x); + } + } + } + + @ParametersAreNonnullByDefault + private void tickUniversalLocation(UUID uuid, Location l, @Nonnull Set tickers) { + var data = StorageCacheUtils.getUniversalData(uuid, l); + var item = SlimefunItem.getById(data.getSfId()); + + if (item != null && item.getBlockTicker() != null) { + if (item.isDisabledIn(l.getWorld())) { + return; + } + + try { + if (item.getBlockTicker().isSynchronized()) { + Slimefun.getProfiler().scheduleEntries(1); + item.getBlockTicker().update(); + + /** + * We are inserting a new timestamp because synchronized actions + * are always ran with a 50ms delay (1 game tick) + */ + Slimefun.runSync(() -> { + if (data.isPendingRemove()) { + return; + } + tickBlock(l, item, data, System.nanoTime()); }); } else { long timestamp = Slimefun.getProfiler().newEntry(); item.getBlockTicker().update(); - Block b = l.getBlock(); - tickBlock(l, b, item, blockData, timestamp); + tickBlock(l, item, data, timestamp); } tickers.add(item.getBlockTicker()); @@ -181,20 +230,20 @@ private void tickLocation(@Nonnull Set tickers, @Nonnull Location l } @ParametersAreNonnullByDefault - private void tickBlock(Location l, Block b, SlimefunItem item, ASlimefunDataContainer data, long timestamp) { + private void tickBlock(Location l, SlimefunItem item, ASlimefunDataContainer data, long timestamp) { try { if (data instanceof SlimefunBlockData blockData) { if (item.getBlockTicker().isUniversal()) { - Slimefun.logger().log(Level.WARNING, "BlockTicker is universal even identified as non-universal!"); + Slimefun.logger().log(Level.WARNING, "BlockTicker is universal but identified as non-universal!"); return; } - item.getBlockTicker().tick(b, item, blockData); + item.getBlockTicker().tick(l.getBlock(), item, blockData); } else if (data instanceof SlimefunUniversalData universalData) { if (!item.getBlockTicker().isUniversal()) { - Slimefun.logger().log(Level.WARNING, "BlockTicker is non-universal even identified as universal!"); + Slimefun.logger().log(Level.WARNING, "BlockTicker is non-universal but identified as universal!"); return; } - item.getBlockTicker().tick(b, item, universalData); + item.getBlockTicker().tick(l.getBlock(), item, universalData); } else { throw new IllegalStateException( "Unable to tick abnormal blockdata @" + LocationUtils.locationToString(l)); @@ -276,7 +325,7 @@ public Map> getLocations() { public Set getLocations(@Nonnull Chunk chunk) { Validate.notNull(chunk, "The Chunk cannot be null!"); - Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), new HashSet<>()); + Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptySet()); return Collections.unmodifiableSet(locations); } @@ -289,15 +338,41 @@ public Set getLocations(@Nonnull Chunk chunk) { public void enableTicker(@Nonnull Location l) { Validate.notNull(l, "Location cannot be null!"); - synchronized (tickingLocations) { - tickingLocations - .computeIfAbsent( - new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4), - k -> new HashSet<>()) - .add(l); + ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); + + /* + Note that all the values in #tickingLocations must be thread-safe. + Thus, the choice is between the CHM KeySet or a synchronized set. + The CHM KeySet was chosen since it at least permits multiple concurrent + reads without blocking. + */ + Set newValue = ConcurrentHashMap.newKeySet(); + Set oldValue = tickingLocations.putIfAbsent(chunk, newValue); + + /** + * This is faster than doing computeIfAbsent(...) + * on a ConcurrentHashMap because it won't block the Thread for too long + */ + if (oldValue != null) { + oldValue.add(l); + } else { + newValue.add(l); } } + /** + * This enables the ticker at the given {@link Location} and adds it to our "queue". + * + * @param l + * The {@link Location} to activate + */ + public void enableTicker(@Nonnull UUID uuid, @Nonnull Location l) { + Validate.notNull(uuid, "Universal ID cannot be null!"); + Validate.notNull(l, "Location cannot be null!"); + + tickingUniversalLocations.putIfAbsent(uuid, l); + } + /** * This method disables the ticker at the given {@link Location} and removes it from our internal * "queue". @@ -322,6 +397,21 @@ public void disableTicker(@Nonnull Location l) { } } + /** + * This method disables the ticker at the given {@link UUID} and removes it from our internal + * "queue". + * + * @param uuid + * The {@link UUID} to remove + */ + public void disableTicker(@Nonnull UUID uuid) { + Validate.notNull(uuid, "Universal Data ID cannot be null!"); + + synchronized (tickingUniversalLocations) { + tickingUniversalLocations.remove(uuid); + } + } + public void setPaused(boolean isPaused) { paused = isPaused; } From 841396dfd2fc0e6a45dd644ca220c9cad837e745 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 22 Jul 2024 00:19:53 +0800 Subject: [PATCH 24/42] fix(unidata): huge fix for universal data --- .../norain/slimefun4/SlimefunExtended.java | 2 + .../controller/BlockDataController.java | 119 +++++++++++------- .../controller/SlimefunUniversalData.java | 2 +- .../slimefun4/storage/util/LocationUtils.java | 4 + .../storage/util/StorageCacheUtils.java | 49 +++++++- .../core/services/AutoSavingService.java | 12 +- .../slimefun4/implementation/Slimefun.java | 6 +- .../items/androids/ProgrammableAndroid.java | 2 +- .../listeners/BlockListener.java | 16 ++- .../listeners/DebugFishListener.java | 65 ++++++---- .../SlimefunItemInteractListener.java | 83 +++++++----- .../implementation/tasks/TickerTask.java | 6 +- .../Slimefun/api/inventory/UniversalMenu.java | 6 + 13 files changed, 256 insertions(+), 116 deletions(-) diff --git a/src/main/java/city/norain/slimefun4/SlimefunExtended.java b/src/main/java/city/norain/slimefun4/SlimefunExtended.java index adacde99bb..2aa92eaf0c 100644 --- a/src/main/java/city/norain/slimefun4/SlimefunExtended.java +++ b/src/main/java/city/norain/slimefun4/SlimefunExtended.java @@ -15,6 +15,8 @@ public final class SlimefunExtended { private static void checkDebug() { if ("true".equals(System.getProperty("slimefun.database.debug"))) { databaseDebugMode = true; + + Slimefun.getSQLProfiler().start(); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 372073bfa6..93614fae38 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -107,8 +107,8 @@ public class BlockDataController extends ADataController { /** * 初始化数据控制器 * - * @param dataAdapter 使用的 {@link IDataSourceAdapter} - * @param maxReadThread 最大数据库读线程数 + * @param dataAdapter 使用的 {@link IDataSourceAdapter} + * @param maxReadThread 最大数据库读线程数 * @param maxWriteThread 最大数据库写线程数 */ @Override @@ -126,6 +126,16 @@ private void initLoadData() { case LOAD_WITH_CHUNK -> loadLoadedChunks(); case LOAD_ON_STARTUP -> loadLoadedWorlds(); } + + Bukkit.getScheduler() + .runTaskLater( + Slimefun.instance(), + () -> { + initLoading = true; + loadUniversalData(); + initLoading = false; + }, + 1); } /** @@ -167,8 +177,8 @@ private void loadLoadedChunks() { /** * 初始化延时加载任务 * - * @param p 插件实例 - * @param delayedSecond 首次执行延时 + * @param p 插件实例 + * @param delayedSecond 首次执行延时 * @param forceSavePeriod 强制保存周期 */ public void initDelayedSaving(Plugin p, int delayedSecond, int forceSavePeriod) { @@ -211,8 +221,8 @@ public void setDelayedSavingEnable(boolean isEnable) { * @param l Slimefun 方块位置 {@link Location} * @param sfId Slimefun 物品 ID {@link SlimefunItem#getId()} * @return 方块数据, 可能会返回两类数据 - * {@link SlimefunBlockData} - * {@link SlimefunUniversalData} + * {@link SlimefunBlockData} + * {@link SlimefunUniversalData} */ @Nonnull public ASlimefunDataContainer createBlock(Location l, String sfId) { @@ -333,6 +343,7 @@ public void removeUniversalData(UUID uuid) { } toRemove.setPendingRemove(true); + removeUniversalBlockDirectly(uuid); var menu = toRemove.getUniversalMenu(); if (menu != null) { @@ -342,8 +353,6 @@ public void removeUniversalData(UUID uuid) { if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { Slimefun.getTickerTask().disableTicker(uuid); } - - removeUniversalBlockDirectly(uuid); } void removeBlockDirectly(Location l) { @@ -427,7 +436,7 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { /** * Get slimefun universal data * - * @param uuid universal data uuid {@link UUID} + * @param uuid universal data uuid {@link UUID} */ @Nullable public SlimefunUniversalData getUniversalData(@Nonnull UUID uuid) { checkDestroy(); @@ -450,7 +459,7 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { /** * Get slimefun universal data asynchronous * - * @param uuid universal data uuid {@link UUID} + * @param uuid universal data uuid {@link UUID} * @param callback operation when block data fetched {@link IAsyncReadCallback} */ public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback callback) { @@ -460,7 +469,7 @@ public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback getUniversalDataFromCache(@Nonnull Location l) { checkDestroy(); @@ -598,31 +607,6 @@ public void loadChunk(Chunk chunk, boolean isNewChunk) { } }); - // 按区块对应世界加载通用数据 - - var uniKey = new RecordKey(DataScope.UNIVERSAL_RECORD); - uniKey.addField(FieldKey.LAST_PRESENT); - // FIXME: 不应该在区块加载中再直接加载全世界 - uniKey.addCondition(FieldKey.LAST_PRESENT, chunk.getWorld().getName() + ";%"); - getData(uniKey, true).forEach(data -> { - var sfId = data.get(FieldKey.SLIMEFUN_ID); - var sfItem = SlimefunItem.getById(sfId); - - if (sfItem == null) { - return; - } - - var uuid = data.getUUID(FieldKey.UNIVERSAL_UUID); - var location = LocationUtils.toLocation(data.get(FieldKey.LAST_PRESENT)); - - var cache = getUniversalDataFromCache(uuid); - var uniData = cache == null ? new SlimefunUniversalData(uuid, location, sfId) : cache; - - if (sfItem.loadDataByDefault()) { - scheduleReadTask(() -> loadUniversalData(uniData)); - } - }); - Bukkit.getPluginManager().callEvent(new SlimefunChunkDataLoadEvent(chunkData)); } @@ -646,6 +630,32 @@ public void loadWorld(World world) { Level.INFO, "世界 {0} 数据加载完成, 耗时 {1}ms", new Object[] {worldName, (System.currentTimeMillis() - start)}); } + public void loadUniversalData() { + var uniKey = new RecordKey(DataScope.UNIVERSAL_RECORD); + uniKey.addField(FieldKey.UNIVERSAL_UUID); + uniKey.addField(FieldKey.SLIMEFUN_ID); + uniKey.addField(FieldKey.LAST_PRESENT); + + getData(uniKey).forEach(data -> { + var sfId = data.get(FieldKey.SLIMEFUN_ID); + var sfItem = SlimefunItem.getById(sfId); + + if (sfItem == null) { + return; + } + + var uuid = data.getUUID(FieldKey.UNIVERSAL_UUID); + var location = LocationUtils.toLocation(data.get(FieldKey.LAST_PRESENT)); + + var cache = getUniversalDataFromCache(uuid); + var uniData = cache == null ? new SlimefunUniversalData(uuid, location, sfId) : cache; + + if (sfItem.loadDataByDefault()) { + scheduleReadTask(() -> loadUniversalData(uniData)); + } + }); + } + private void loadChunkData(SlimefunChunkData chunkData) { if (chunkData.isDataLoaded()) { return; @@ -781,13 +791,13 @@ public void loadUniversalData(SlimefunUniversalData uniData) { } var sfItem = SlimefunItem.getById(uniData.getSfId()); - if (sfItem != null - && sfItem.isTicking() - && !uniData.getLastPresent() - .getBlock() - .getType() - .equals(sfItem.getItem().getType())) { - Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); + + if (sfItem != null && sfItem.isTicking()) { + loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); + + if (!uniData.getLastPresent().getBlock().getType().isAir()) { + Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); + } } } finally { lock.unlock(key); @@ -828,6 +838,21 @@ public void saveAllBlockInventories() { })); } + public void saveAllUniversalInventories() { + var uniData = new HashSet<>(loadedUniversalData.values()); + uniData.forEach(data -> { + if (data.isPendingRemove() || !data.isDataLoaded()) { + return; + } + var menu = data.getUniversalMenu(); + if (menu == null || !menu.isDirty()) { + return; + } + + saveUniversalInventory(data); + }); + } + public void saveBlockInventory(SlimefunBlockData blockData) { var newInv = blockData.getMenuContents(); List> lastSave; @@ -899,7 +924,10 @@ public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) }); } - public void saveUniversalInventory(@Nonnull UUID universalID, UniversalMenu menu) { + public void saveUniversalInventory(@Nonnull SlimefunUniversalData universalData) { + var menu = universalData.getUniversalMenu(); + var universalID = universalData.getUUID(); + var newInv = menu.getContents(); List> lastSave; if (newInv == null) { @@ -1016,6 +1044,7 @@ private void scheduleUniversalInvUpdate(ScopeKey scopeKey, RecordKey reqKey, UUI @Override public void shutdown() { saveAllBlockInventories(); + saveAllUniversalInventories(); if (enableDelayedSaving) { looperTask.cancel(); executeAllDelayedTasks(); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index 6ea4c8f727..e7f6eb17cc 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -17,7 +17,7 @@ public class SlimefunUniversalData extends ASlimefunDataContainer { @Setter @Getter - private volatile Location lastPresent; + @Nullable private volatile Location lastPresent; @Setter @Getter diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java index db03bc4585..d8826570f5 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/LocationUtils.java @@ -15,6 +15,10 @@ public static String getChunkKey(Chunk chunk) { } public static Location toLocation(String lKey) { + if (lKey == null || lKey.isEmpty()) { + return null; + } + var strArr = lKey.split(";"); var loc = strArr[1].split(":"); return new Location( diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 1872d130d9..96800f8aaa 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -3,6 +3,7 @@ import com.google.common.base.Preconditions; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ADataContainer; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -10,6 +11,7 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; @@ -50,7 +52,13 @@ public static boolean isBlock(Location l, String id) { @ParametersAreNonnullByDefault @Nullable public static SlimefunItem getSfItem(Location l) { var blockData = getBlock(l); - return blockData == null ? null : SlimefunItem.getById(blockData.getSfId()); + + if (blockData != null) { + return SlimefunItem.getById(blockData.getSfId()); + } else { + var universalData = getUniversalData(l.getBlock()); + return universalData == null ? null : SlimefunItem.getById(universalData.getSfId()); + } } @ParametersAreNonnullByDefault @@ -161,6 +169,18 @@ public static void removeData(Location loc, String key) { return uniData.getUniversalMenu(); } + public static boolean isBlockPendingRemove(@Nonnull Block block) { + if (hasBlock(block.getLocation())) { + return getBlock(block.getLocation()).isPendingRemove(); + } + + if (hasUniversalBlock(block.getLocation())) { + return getUniversalData(block).isPendingRemove(); + } + + return false; + } + public static void requestLoad(ADataContainer data) { if (data.isDataLoaded()) { return; @@ -198,6 +218,14 @@ public void onResult(SlimefunUniversalData result) { } } + public static void executeAfterLoad(ASlimefunDataContainer data, Runnable execute, boolean runOnMainThread) { + if (data instanceof SlimefunBlockData blockData) { + executeAfterLoad(blockData, execute, runOnMainThread); + } else if (data instanceof SlimefunUniversalData universalData) { + executeAfterLoad(universalData, execute, runOnMainThread); + } + } + public static void executeAfterLoad(SlimefunBlockData data, Runnable execute, boolean runOnMainThread) { if (data.isDataLoaded()) { execute.run(); @@ -216,4 +244,23 @@ public void onResult(SlimefunBlockData result) { } }); } + + public static void executeAfterLoad(SlimefunUniversalData data, Runnable execute, boolean runOnMainThread) { + if (data.isDataLoaded()) { + execute.run(); + return; + } + + Slimefun.getDatabaseManager().getBlockDataController().loadUniversalDataAsync(data, new IAsyncReadCallback<>() { + @Override + public boolean runOnMainThread() { + return runOnMainThread; + } + + @Override + public void onResult(SlimefunUniversalData result) { + execute.run(); + } + }); + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/AutoSavingService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/AutoSavingService.java index cd80124363..560c6d5510 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/AutoSavingService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/AutoSavingService.java @@ -35,9 +35,15 @@ public void start(@Nonnull Slimefun plugin, int interval) { .getScheduler() .runTaskTimerAsynchronously( plugin, - () -> Slimefun.getDatabaseManager() - .getBlockDataController() - .saveAllBlockInventories(), + () -> { + Slimefun.getDatabaseManager() + .getBlockDataController() + .saveAllBlockInventories(); + + Slimefun.getDatabaseManager() + .getBlockDataController() + .saveAllUniversalInventories(); + }, 2000L, interval * 60L * 20L); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java index 668b828c55..c37f3e93f3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java @@ -314,6 +314,9 @@ private void onPluginStart() { cfgManager.load(); registry.load(this); + // Inject downstream extra staff + SlimefunExtended.register(this); + logger.log(Level.INFO, "正在加载数据库..."); if (PlayerProfileMigrator.getInstance().hasOldData() || BlockStorageMigrator.getInstance().hasOldData()) { @@ -706,9 +709,6 @@ private void registerListeners() { new SmithingTableListener(this); new JoinListener(this); - // Inject downstream extra staff - SlimefunExtended.register(this); - // Item-specific Listeners new CoolerListener(this, (Cooler) SlimefunItems.COOLER.getItem()); new SeismicAxeListener(this, (SeismicAxe) SlimefunItems.SEISMIC_AXE.getItem()); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index ff16bcde45..cf1f228c22 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -274,7 +274,7 @@ public AndroidFuelSource getFuelSource() { public void preRegister() { super.preRegister(); - addItemHandler(new BlockTicker() { + addItemHandler(new BlockTicker(true) { @Override public void tick(Block b, SlimefunItem item, SlimefunUniversalData data) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 7f35917313..be518a77c9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -158,11 +158,13 @@ public void onBlockPlace(BlockPlaceEvent e) { .getBlockDataController() .createBlock(block.getLocation(), sfItem.getId()); - if (data instanceof SlimefunUniversalData - && Slimefun.getBlockDataService().isTileEntity(block.getType())) { - Slimefun.getBlockDataService().setUniversalDataUUID(block, data.getKey()); - } else { - throw new IllegalStateException("You must use pdc support material for this Slimefun item!"); + if (data instanceof SlimefunUniversalData) { + if (Slimefun.getBlockDataService().isTileEntity(block.getType())) { + Slimefun.getBlockDataService().setUniversalDataUUID(block, data.getKey()); + } else { + throw new IllegalStateException( + "You must use pdc support material for this Slimefun item!"); + } } sfItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(e)); @@ -185,7 +187,9 @@ public void onBlockBreak(BlockBreakEvent e) { var heldItem = e.getPlayer().getInventory().getItemInMainHand(); var block = e.getBlock(); - var blockData = StorageCacheUtils.getBlock(block.getLocation()); + var blockData = StorageCacheUtils.hasBlock(block.getLocation()) + ? StorageCacheUtils.getBlock(block.getLocation()) + : StorageCacheUtils.getUniversalData(block); // If there is a Slimefun Block here, call our BreakEvent and, if cancelled, cancel this event // and return diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index f2feed1933..d1524743a9 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -1,7 +1,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.common.ChatColors; @@ -106,24 +108,45 @@ private void onRightClick(Player p, Block b, BlockFace face) { return; } - var controller = Slimefun.getDatabaseManager().getBlockDataController(); - var blockData = controller.getBlockDataFromCache(b.getLocation()); - if (blockData != null) { + if (StorageCacheUtils.hasBlock(b.getLocation()) || StorageCacheUtils.hasUniversalBlock(b.getLocation())) { + var data = StorageCacheUtils.hasBlock(b.getLocation()) + ? StorageCacheUtils.getBlock(b.getLocation()) + : StorageCacheUtils.getUniversalData(b); + try { - if (blockData.isDataLoaded()) { - sendInfo(p, b); + if (data.isDataLoaded()) { + sendInfo(p, b, data); } else { - controller.loadBlockDataAsync(blockData, new IAsyncReadCallback<>() { - @Override - public boolean runOnMainThread() { - return true; - } - - @Override - public void onResult(SlimefunBlockData result) { - sendInfo(p, b); - } - }); + if (data instanceof SlimefunBlockData blockData) { + Slimefun.getDatabaseManager() + .getBlockDataController() + .loadBlockDataAsync(blockData, new IAsyncReadCallback<>() { + @Override + public boolean runOnMainThread() { + return true; + } + + @Override + public void onResult(SlimefunBlockData result) { + sendInfo(p, b, result); + } + }); + } else { + SlimefunUniversalData universalData = (SlimefunUniversalData) data; + Slimefun.getDatabaseManager() + .getBlockDataController() + .loadUniversalDataAsync(universalData, new IAsyncReadCallback<>() { + @Override + public boolean runOnMainThread() { + return true; + } + + @Override + public void onResult(SlimefunUniversalData result) { + sendInfo(p, b, result); + } + }); + } } } catch (Exception x) { Slimefun.logger().log(Level.SEVERE, "An Exception occurred while using a Debug-Fish", x); @@ -153,9 +176,8 @@ public void onResult(SlimefunBlockData result) { } @ParametersAreNonnullByDefault - private void sendInfo(Player p, Block b) { - var blockData = StorageCacheUtils.getBlock(b.getLocation()); - SlimefunItem item = SlimefunItem.getById(blockData.getSfId()); + private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { + SlimefunItem item = SlimefunItem.getById(data.getSfId()); p.sendMessage(" "); p.sendMessage( @@ -176,7 +198,8 @@ private void sendInfo(Player p, Block b) { } } - if (blockData.getBlockMenu() != null) { + if ((data instanceof SlimefunBlockData bd && bd.getBlockMenu() != null) + || (data instanceof SlimefunUniversalData ud && ud.getUniversalMenu() != null)) { p.sendMessage(ChatColors.color("&dInventory: " + greenCheckmark)); } else { p.sendMessage(ChatColors.color("&dInventory: " + redCross)); @@ -233,7 +256,7 @@ private void sendInfo(Player p, Block b) { } } - blockData.getAllData().forEach((k, v) -> p.sendMessage(ChatColors.color("&6" + k + ": " + v))); + data.getAllData().forEach((k, v) -> p.sendMessage(ChatColors.color("&6" + k + ": " + v))); p.sendMessage(" "); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index 9dc99b87f1..50a7c2a42f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -2,9 +2,11 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; @@ -34,11 +36,9 @@ * * @author TheBusyBiscuit * @author Liruxo - * * @see PlayerRightClickEvent * @see ItemUseHandler * @see BlockUseHandler - * */ public class SlimefunItemInteractListener implements Listener { @@ -56,11 +56,7 @@ public void onRightClick(PlayerInteractEvent e) { // Fixes #4087 - Prevents players from interacting with a block that is about to be deleted // We especially don't want to open inventories as that can cause duplication - if (e.getClickedBlock() != null - && StorageCacheUtils.hasBlock(e.getClickedBlock().getLocation()) - && StorageCacheUtils.hasUniversalBlock(e.getClickedBlock().getLocation()) - && StorageCacheUtils.getBlock(e.getClickedBlock().getLocation()) - .isPendingRemove()) { + if (e.getClickedBlock() != null && StorageCacheUtils.isBlockPendingRemove(e.getClickedBlock())) { e.setCancelled(true); return; } @@ -147,37 +143,62 @@ private void openInventory(Player p, SlimefunItem item, Block clickedBlock, Play if (!p.isSneaking() || event.getItem().getType() == Material.AIR) { event.getInteractEvent().setCancelled(true); - var blockData = StorageCacheUtils.getBlock(clickedBlock.getLocation()); - if (blockData == null) { - var uniMenu = StorageCacheUtils.getUniversalMenu(clickedBlock); + if (item instanceof UniversalDataSupport) { + var uniData = StorageCacheUtils.getUniversalData(clickedBlock); - if (uniMenu != null) { - openMenu(uniMenu, clickedBlock, p); + if (uniData == null) { + return; } - return; - } + if (uniData.isDataLoaded()) { + openMenu(uniData.getUniversalMenu(), clickedBlock, p); + } else { + Slimefun.getDatabaseManager() + .getBlockDataController() + .loadUniversalDataAsync(uniData, new IAsyncReadCallback<>() { + @Override + public boolean runOnMainThread() { + return true; + } - if (blockData.isDataLoaded()) { - openMenu(blockData.getBlockMenu(), clickedBlock, p); + @Override + public void onResult(SlimefunUniversalData result) { + if (!p.isOnline()) { + return; + } + + openMenu(result.getUniversalMenu(), clickedBlock, p); + } + }); + } } else { - Slimefun.getDatabaseManager() - .getBlockDataController() - .loadBlockDataAsync(blockData, new IAsyncReadCallback<>() { - @Override - public boolean runOnMainThread() { - return true; - } - - @Override - public void onResult(SlimefunBlockData result) { - if (!p.isOnline()) { - return; + var blockData = StorageCacheUtils.getBlock(clickedBlock.getLocation()); + + if (blockData == null) { + return; + } + + if (blockData.isDataLoaded()) { + openMenu(blockData.getBlockMenu(), clickedBlock, p); + } else { + Slimefun.getDatabaseManager() + .getBlockDataController() + .loadBlockDataAsync(blockData, new IAsyncReadCallback<>() { + @Override + public boolean runOnMainThread() { + return true; } - openMenu(result.getBlockMenu(), clickedBlock, p); - } - }); + @Override + public void onResult(SlimefunBlockData result) { + if (!p.isOnline()) { + return; + } + + openMenu(result.getBlockMenu(), clickedBlock, p); + } + }); + } } } } catch (Exception | LinkageError x) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index a3296040dc..03ecaee6bd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -234,14 +234,12 @@ private void tickBlock(Location l, SlimefunItem item, ASlimefunDataContainer dat try { if (data instanceof SlimefunBlockData blockData) { if (item.getBlockTicker().isUniversal()) { - Slimefun.logger().log(Level.WARNING, "BlockTicker is universal but identified as non-universal!"); - return; + throw new IllegalStateException("BlockTicker is universal but identified as non-universal!"); } item.getBlockTicker().tick(l.getBlock(), item, blockData); } else if (data instanceof SlimefunUniversalData universalData) { if (!item.getBlockTicker().isUniversal()) { - Slimefun.logger().log(Level.WARNING, "BlockTicker is non-universal but identified as universal!"); - return; + throw new IllegalStateException("BlockTicker is non-universal but identified as universal!"); } item.getBlockTicker().tick(l.getBlock(), item, universalData); } else { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java index e80e6c02af..afd6699509 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java @@ -17,6 +17,9 @@ public class UniversalMenu extends DirtyChestMenu { public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { super(preset); this.uuid = uuid; + + preset.clone(this); + this.getContents(); } public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { @@ -30,6 +33,9 @@ public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, It } addItem(i, item); } + + preset.clone(this); + this.getContents(); } /** From b98fe2cb7d8db7375cb085c4b90285cfbe8daba5 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 22 Jul 2024 00:33:11 +0800 Subject: [PATCH 25/42] chore: do not modify build artifact name --- .mvn/maven-git-versioning-extension.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.mvn/maven-git-versioning-extension.xml b/.mvn/maven-git-versioning-extension.xml index 11980355ba..1677a00c94 100644 --- a/.mvn/maven-git-versioning-extension.xml +++ b/.mvn/maven-git-versioning-extension.xml @@ -11,14 +11,6 @@ ${commit.short}-Insider - - test/(.+) - ${ref}-${commit.short} - - - feat/(.+) - ${ref}-${commit.short} - ([0-9].*)> ${1} From 2b5b82274b288bfcf1750f26a89b213862aee87e Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 22 Jul 2024 00:36:24 +0800 Subject: [PATCH 26/42] fix(ci): fix version regex --- .github/workflows/pr-checker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index 0a91e9c360..233110200c 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -54,7 +54,7 @@ jobs: echo "SHORT_COMMIT_HASH=$SHORT_COMMIT_HASH" >> "$GITHUB_ENV" echo "SHORT_COMMIT_HASH=$SHORT_COMMIT_HASH" >> "$GITHUB_OUTPUT" echo "JAR_VERSION=$JAR_VERSION" >> "$GITHUB_ENV" - sed -i "s/5.0-SNAPSHOT<\/version>/$JAR_VERSION<\/version>/g" pom.xml + sed -i "s/UNOFFICIAL<\/version>/$JAR_VERSION<\/version>/g" pom.xml - name: Upload the artifact uses: actions/upload-artifact@v3 From 291360a4e20559cb8c7ca4f730ce131c65719e8d Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 1 Aug 2024 07:25:49 +0800 Subject: [PATCH 27/42] fix: debug fish unable to identify universal block --- .../controller/BlockDataController.java | 5 ++- .../storage/util/StorageCacheUtils.java | 13 +++++- .../listeners/DebugFishListener.java | 4 ++ .../api/inventory/UniversalMenuPreset.java | 44 ++++++++++++------- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 93614fae38..794869a8b8 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -782,7 +782,10 @@ public void loadUniversalData(SlimefunUniversalData uniData) { getData(menuKey) .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); - uniData.setUniversalMenu(new UniversalMenu(menuPreset, uniData.getUUID(), inv)); + + var universalMenu = new UniversalMenu(menuPreset, uniData.getUUID(), inv); + + uniData.setUniversalMenu(universalMenu); var content = uniData.getMenuContents(); if (content != null) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 96800f8aaa..799aa848fa 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -102,7 +102,7 @@ public static void removeData(Location loc, String key) { } @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalData(UUID uuid, Location l) { + @Nullable public static SlimefunUniversalData getUniversalData(UUID uuid) { var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); if (uniData == null) { @@ -117,6 +117,17 @@ public static void removeData(Location loc, String key) { return uniData; } + @ParametersAreNonnullByDefault + @Nullable public static SlimefunUniversalData getUniversalData(UUID uuid, Location l) { + var uniData = getUniversalData(uuid); + + if (uniData != null) { + uniData.setLastPresent(l); + } + + return uniData; + } + /** * Get universal data from block *

diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index d1524743a9..d843947e3a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -205,6 +205,10 @@ private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { p.sendMessage(ChatColors.color("&dInventory: " + redCross)); } + if (data instanceof SlimefunUniversalData) { + p.sendMessage(ChatColors.color("&dUniversal Item: " + greenCheckmark)); + } + if (item.isTicking()) { p.sendMessage(ChatColors.color("&dTicker: " + greenCheckmark)); p.sendMessage(ChatColors.color( diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java index 9ec4b8a2f1..f71c24514b 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -1,5 +1,6 @@ package me.mrCookieSlime.Slimefun.api.inventory; +import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -20,27 +21,40 @@ public void newInstance(@Nonnull UniversalMenu menu, @Nonnull Block b) { // This method can optionally be overridden by implementations } - protected void clone(@Nonnull UniversalMenu menu, @Nonnull Block b) { - menu.setPlayerInventoryClickable(true); + @Override + protected void clone(@Nonnull DirtyChestMenu menu) { + if (menu instanceof UniversalMenu universalMenu) { + var uniData = StorageCacheUtils.getUniversalData(universalMenu.getUuid()); - for (int slot : occupiedSlots) { - menu.addItem(slot, getItemInSlot(slot)); - } + if (uniData == null) { + return; + } - if (getSize() > -1) { - menu.addItem(getSize() - 1, null); - } + if (!uniData.isDataLoaded()) { + StorageCacheUtils.requestLoad(uniData); + } - newInstance(menu, b); + menu.setPlayerInventoryClickable(true); - for (int slot = 0; slot < 54; slot++) { - if (getMenuClickHandler(slot) != null) { - menu.addMenuClickHandler(slot, getMenuClickHandler(slot)); + for (int slot : occupiedSlots) { + menu.addItem(slot, getItemInSlot(slot)); } - } - menu.addMenuOpeningHandler(getMenuOpeningHandler()); - menu.addMenuCloseHandler(getMenuCloseHandler()); + if (getSize() > -1) { + menu.addItem(getSize() - 1, null); + } + + newInstance(universalMenu, uniData.getLastPresent().getBlock()); + + for (int slot = 0; slot < 54; slot++) { + if (getMenuClickHandler(slot) != null) { + menu.addMenuClickHandler(slot, getMenuClickHandler(slot)); + } + } + + menu.addMenuOpeningHandler(getMenuOpeningHandler()); + menu.addMenuCloseHandler(getMenuCloseHandler()); + } } @Nullable public static UniversalMenuPreset getPreset(@Nullable String id) { From e3141e5f0f0c5edcd6bde9462bb7fd78a1e5c657 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Wed, 7 Aug 2024 09:15:24 +0800 Subject: [PATCH 28/42] fix(unidata): more fix on universal menu --- .../controller/BlockDataController.java | 18 ++++++--- .../storage/util/StorageCacheUtils.java | 34 ++++++++++++++--- .../items/androids/ProgrammableAndroid.java | 9 ++++- .../listeners/DebugFishListener.java | 3 +- .../implementation/tasks/TickerTask.java | 2 +- .../Slimefun/api/inventory/UniversalMenu.java | 22 +++++++++++ .../api/inventory/UniversalMenuPreset.java | 37 ++++++++++--------- 7 files changed, 92 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 794869a8b8..0abfd5615a 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -441,6 +441,10 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { @Nullable public SlimefunUniversalData getUniversalData(@Nonnull UUID uuid) { checkDestroy(); + if (loadedUniversalData.containsKey(uuid) && loadedUniversalData.get(uuid) != null) { + return loadedUniversalData.get(uuid); + } + var key = new RecordKey(DataScope.UNIVERSAL_RECORD); key.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); key.addField(FieldKey.SLIMEFUN_ID); @@ -448,6 +452,9 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { var result = getData(key); + Slimefun.logger().log(Level.INFO, "Got data {0}", result.stream().map(set -> set.getAll() + .toString())); + return result.isEmpty() ? null : new SlimefunUniversalData( @@ -650,6 +657,8 @@ public void loadUniversalData() { var cache = getUniversalDataFromCache(uuid); var uniData = cache == null ? new SlimefunUniversalData(uuid, location, sfId) : cache; + Slimefun.logger().log(Level.INFO, "Loaded universal data {0}", uuid); + if (sfItem.loadDataByDefault()) { scheduleReadTask(() -> loadUniversalData(uniData)); } @@ -714,6 +723,7 @@ public void loadBlockData(SlimefunBlockData blockData) { getData(menuKey) .forEach(record -> inv[record.getInt(FieldKey.INVENTORY_SLOT)] = record.getItemStack(FieldKey.INVENTORY_ITEM)); + blockData.setBlockMenu(new BlockMenu(menuPreset, blockData.getLocation(), inv)); var content = blockData.getMenuContents(); @@ -783,9 +793,7 @@ public void loadUniversalData(SlimefunUniversalData uniData) { .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); - var universalMenu = new UniversalMenu(menuPreset, uniData.getUUID(), inv); - - uniData.setUniversalMenu(universalMenu); + uniData.setUniversalMenu(new UniversalMenu(menuPreset, uniData, inv)); var content = uniData.getMenuContents(); if (content != null) { @@ -796,12 +804,12 @@ public void loadUniversalData(SlimefunUniversalData uniData) { var sfItem = SlimefunItem.getById(uniData.getSfId()); if (sfItem != null && sfItem.isTicking()) { - loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); - if (!uniData.getLastPresent().getBlock().getType().isAir()) { Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); } } + + loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); } finally { lock.unlock(key); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 799aa848fa..dd37918fba 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -30,7 +30,7 @@ public class StorageCacheUtils { @ParametersAreNonnullByDefault public static boolean hasBlock(Location l) { - return getBlock(l) != null; + return getBlock(l) != null || getUniversalData(l.getBlock()) != null; } @ParametersAreNonnullByDefault @@ -64,7 +64,18 @@ public static boolean isBlock(Location l, String id) { @ParametersAreNonnullByDefault @Nullable public static String getData(Location loc, String key) { var blockData = getBlock(loc); - return blockData == null ? null : blockData.getData(key); + + if (blockData != null) { + return blockData.getData(key); + } else { + var uniData = getUniversalData(loc.getBlock()); + + if (uniData == null) { + return null; + } + + return uniData.getData(key); + } } @ParametersAreNonnullByDefault @@ -76,14 +87,25 @@ public static boolean isBlock(Location l, String id) { @ParametersAreNonnullByDefault public static void setData(Location loc, String key, String val) { var block = getBlock(loc); - Preconditions.checkNotNull(block); - - block.setData(key, val); + if (block != null) { + block.setData(key, val); + } else { + var uni = getUniversalData(loc.getBlock()); + Preconditions.checkNotNull(uni); + uni.setData(key, val); + } } @ParametersAreNonnullByDefault public static void removeData(Location loc, String key) { - getBlock(loc).removeData(key); + var block = getBlock(loc); + if (block != null) { + block.removeData(key); + } else { + var uni = getUniversalData(loc.getBlock()); + Preconditions.checkNotNull(uni); + uni.removeData(key); + } } @ParametersAreNonnullByDefault diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index cf1f228c22..7689df1cad 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -225,7 +225,7 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro } var uniData = - Slimefun.getDatabaseManager().getBlockDataController().getUniversalData(uuid.get()); + Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid.get()); if (uniData != null) { if (!e.getPlayer().hasPermission("slimefun.android.bypass") @@ -1037,7 +1037,7 @@ protected void move(Block from, BlockFace face, Block to) { + LocationUtils.locationToString(from.getLocation())); } - OfflinePlayer owner = Bukkit.getOfflinePlayer(uniData.getData("owner")); + OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(uniData.getData("owner"))); if (!Slimefun.getProtectionManager().hasPermission(owner, to.getLocation(), Interaction.PLACE_BLOCK)) { return; @@ -1051,6 +1051,8 @@ protected void move(Block from, BlockFace face, Block to) { return; } + Slimefun.getTickerTask().disableTicker(uniData.getUUID()); + to.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { if (data instanceof Rotatable rotatable) { rotatable.setRotation(face.getOppositeFace()); @@ -1068,6 +1070,9 @@ protected void move(Block from, BlockFace face, Block to) { from.setType(Material.AIR); uniData.setLastPresent(to.getLocation()); + uniData.getUniversalMenu().update(); + + Slimefun.getTickerTask().enableTicker(uniData.getUUID(), to.getLocation()); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index d843947e3a..e96fce3ab0 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -205,8 +205,9 @@ private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { p.sendMessage(ChatColors.color("&dInventory: " + redCross)); } - if (data instanceof SlimefunUniversalData) { + if (data instanceof SlimefunUniversalData universalData) { p.sendMessage(ChatColors.color("&dUniversal Item: " + greenCheckmark)); + p.sendMessage(ChatColors.color(" &dUUID: " + universalData.getUUID())); } if (item.isTicking()) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index 03ecaee6bd..b81fd2859a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -193,7 +193,7 @@ private void tickLocation(@Nonnull Set tickers, @Nonnull Location l @ParametersAreNonnullByDefault private void tickUniversalLocation(UUID uuid, Location l, @Nonnull Set tickers) { - var data = StorageCacheUtils.getUniversalData(uuid, l); + var data = StorageCacheUtils.getUniversalData(uuid); var item = SlimefunItem.getById(data.getSfId()); if (item != null && item.getBlockTicker() != null) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java index afd6699509..5d5901376b 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java @@ -1,5 +1,6 @@ package me.mrCookieSlime.Slimefun.api.inventory; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import java.util.UUID; import javax.annotation.Nonnull; import lombok.Getter; @@ -38,6 +39,27 @@ public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, It this.getContents(); } + public UniversalMenu( + @Nonnull UniversalMenuPreset preset, @Nonnull SlimefunUniversalData universalData, ItemStack[] contents) { + super(preset); + this.uuid = universalData.getUUID(); + + for (int i = 0; i < contents.length; i++) { + var item = contents[i]; + if (item == null) { + continue; + } + addItem(i, item); + } + + preset.clone(this, universalData.getLastPresent()); + this.getContents(); + } + + public void update() { + preset.clone(this); + } + /** * This method drops the contents of this {@link BlockMenu} on the ground at the given * {@link Location}. diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java index f71c24514b..d5e6a4f01e 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -4,6 +4,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.bukkit.Location; import org.bukkit.block.Block; public abstract class UniversalMenuPreset extends BlockMenuPreset { @@ -30,31 +31,31 @@ protected void clone(@Nonnull DirtyChestMenu menu) { return; } - if (!uniData.isDataLoaded()) { - StorageCacheUtils.requestLoad(uniData); - } + clone(universalMenu, uniData.getLastPresent()); + } + } - menu.setPlayerInventoryClickable(true); + protected void clone(@Nonnull UniversalMenu menu, @Nonnull Location lastPresent) { + menu.setPlayerInventoryClickable(true); - for (int slot : occupiedSlots) { - menu.addItem(slot, getItemInSlot(slot)); - } + for (int slot : occupiedSlots) { + menu.addItem(slot, getItemInSlot(slot)); + } - if (getSize() > -1) { - menu.addItem(getSize() - 1, null); - } + if (getSize() > -1) { + menu.addItem(getSize() - 1, null); + } - newInstance(universalMenu, uniData.getLastPresent().getBlock()); + newInstance(menu, lastPresent.getBlock()); - for (int slot = 0; slot < 54; slot++) { - if (getMenuClickHandler(slot) != null) { - menu.addMenuClickHandler(slot, getMenuClickHandler(slot)); - } + for (int slot = 0; slot < 54; slot++) { + if (getMenuClickHandler(slot) != null) { + menu.addMenuClickHandler(slot, getMenuClickHandler(slot)); } - - menu.addMenuOpeningHandler(getMenuOpeningHandler()); - menu.addMenuCloseHandler(getMenuCloseHandler()); } + + menu.addMenuOpeningHandler(getMenuOpeningHandler()); + menu.addMenuCloseHandler(getMenuCloseHandler()); } @Nullable public static UniversalMenuPreset getPreset(@Nullable String id) { From 34d43763dfa56a4b3d7579ac141d10cfe2439b67 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 8 Aug 2024 14:09:40 +0800 Subject: [PATCH 29/42] fix(unidata): fix recursive problem on init --- .../slimefun4/storage/common/RecordSet.java | 2 + .../controller/BlockDataController.java | 55 +++++++++--------- .../controller/SlimefunUniversalData.java | 8 +-- .../storage/util/StorageCacheUtils.java | 28 ++++----- .../items/androids/FarmerAndroid.java | 2 +- .../items/androids/MinerAndroid.java | 10 ++-- .../items/androids/ProgrammableAndroid.java | 8 +-- .../items/androids/WoodcutterAndroid.java | 2 +- .../listeners/BlockListener.java | 2 +- .../listeners/DebugFishListener.java | 2 +- .../SlimefunItemInteractListener.java | 2 +- .../implementation/tasks/TickerTask.java | 58 +++++++++++++------ .../Slimefun/api/inventory/UniversalMenu.java | 32 +++------- .../api/inventory/UniversalMenuPreset.java | 2 +- 14 files changed, 109 insertions(+), 104 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java index fad59fd8af..a2f571a5a3 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/RecordSet.java @@ -6,8 +6,10 @@ import java.util.Map; import java.util.UUID; import javax.annotation.ParametersAreNonnullByDefault; +import lombok.ToString; import org.bukkit.inventory.ItemStack; +@ToString public class RecordSet { private final Map data; private boolean readonly = false; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 0abfd5615a..9982769f16 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -220,7 +220,7 @@ public void setDelayedSavingEnable(boolean isEnable) { * * @param l Slimefun 方块位置 {@link Location} * @param sfId Slimefun 物品 ID {@link SlimefunItem#getId()} - * @return 方块数据, 可能会返回两类数据 + * @return 方块数据, 由于 {@link SlimefunItem} 的不同会返回两种数据中的一种 * {@link SlimefunBlockData} * {@link SlimefunUniversalData} */ @@ -253,11 +253,12 @@ public SlimefunUniversalData createUniversalData(Location l, String sfId) { var uniData = new SlimefunUniversalData(uuid, l, sfId); uniData.setIsDataLoaded(true); + loadedUniversalData.put(uuid, uniData); var preset = UniversalMenuPreset.getPreset(sfId); if (preset != null) { - uniData.setUniversalMenu(new UniversalMenu(preset, uuid)); + uniData.setUniversalMenu(new UniversalMenu(preset, uuid, l)); } Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uuid, sfId, l); @@ -310,7 +311,13 @@ public void removeBlock(Location l) { var removed = getChunkDataCache(l.getChunk(), true).removeBlockData(l); if (removed == null) { - getUniversalDataFromCache(l).ifPresent(data -> removeUniversalData(data.getUUID())); + getUniversalDataFromCache(l).ifPresentOrElse(data -> removeUniversalData(data.getUUID()), () -> { + if (Bukkit.isPrimaryThread()) { + Slimefun.getBlockDataService() + .getUniversalDataUUID(l.getBlock()) + .ifPresent(this::removeUniversalData); + } + }); return; } @@ -441,10 +448,6 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { @Nullable public SlimefunUniversalData getUniversalData(@Nonnull UUID uuid) { checkDestroy(); - if (loadedUniversalData.containsKey(uuid) && loadedUniversalData.get(uuid) != null) { - return loadedUniversalData.get(uuid); - } - var key = new RecordKey(DataScope.UNIVERSAL_RECORD); key.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); key.addField(FieldKey.SLIMEFUN_ID); @@ -452,9 +455,6 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { var result = getData(key); - Slimefun.logger().log(Level.INFO, "Got data {0}", result.stream().map(set -> set.getAll() - .toString())); - return result.isEmpty() ? null : new SlimefunUniversalData( @@ -482,7 +482,8 @@ public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback loadUniversalData(uniData)); - } + scheduleReadTask(() -> loadUniversalData(uniData)); }); } @@ -780,6 +776,16 @@ public void loadUniversalData(SlimefunUniversalData uniData) { uniData.setIsDataLoaded(true); + var sfItem = SlimefunItem.getById(uniData.getSfId()); + + if (sfItem != null && sfItem.isTicking()) { + if (!uniData.getLastPresent().getBlock().getType().isAir()) { + Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); + } + } + + loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); + var menuPreset = UniversalMenuPreset.getPreset(uniData.getSfId()); if (menuPreset != null) { var menuKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); @@ -793,23 +799,14 @@ public void loadUniversalData(SlimefunUniversalData uniData) { .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); - uniData.setUniversalMenu(new UniversalMenu(menuPreset, uniData, inv)); + uniData.setUniversalMenu( + new UniversalMenu(menuPreset, uniData.getUUID(), uniData.getLastPresent(), inv)); var content = uniData.getMenuContents(); if (content != null) { invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); } } - - var sfItem = SlimefunItem.getById(uniData.getSfId()); - - if (sfItem != null && sfItem.isTicking()) { - if (!uniData.getLastPresent().getBlock().getType().isAir()) { - Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); - } - } - - loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); } finally { lock.unlock(key); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index e7f6eb17cc..f247495c56 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -10,17 +10,13 @@ import org.bukkit.Location; import org.bukkit.inventory.ItemStack; +@Setter +@Getter public class SlimefunUniversalData extends ASlimefunDataContainer { - @Setter - @Getter private volatile UniversalMenu universalMenu; - @Setter - @Getter @Nullable private volatile Location lastPresent; - @Setter - @Getter private volatile boolean pendingRemove = false; @ParametersAreNonnullByDefault diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index dd37918fba..79a9575e6a 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -30,7 +30,7 @@ public class StorageCacheUtils { @ParametersAreNonnullByDefault public static boolean hasBlock(Location l) { - return getBlock(l) != null || getUniversalData(l.getBlock()) != null; + return getBlock(l) != null; } @ParametersAreNonnullByDefault @@ -56,7 +56,7 @@ public static boolean isBlock(Location l, String id) { if (blockData != null) { return SlimefunItem.getById(blockData.getSfId()); } else { - var universalData = getUniversalData(l.getBlock()); + var universalData = getUniversalBlock(l.getBlock()); return universalData == null ? null : SlimefunItem.getById(universalData.getSfId()); } } @@ -68,7 +68,7 @@ public static boolean isBlock(Location l, String id) { if (blockData != null) { return blockData.getData(key); } else { - var uniData = getUniversalData(loc.getBlock()); + var uniData = getUniversalBlock(loc.getBlock()); if (uniData == null) { return null; @@ -79,8 +79,8 @@ public static boolean isBlock(Location l, String id) { } @ParametersAreNonnullByDefault - @Nullable public static String getUniversalData(UUID uuid, Location loc, String key) { - var universalData = getUniversalData(uuid, loc); + @Nullable public static String getUniversalBlock(UUID uuid, Location loc, String key) { + var universalData = getUniversalBlock(uuid, loc); return universalData == null ? null : universalData.getData(key); } @@ -90,7 +90,7 @@ public static void setData(Location loc, String key, String val) { if (block != null) { block.setData(key, val); } else { - var uni = getUniversalData(loc.getBlock()); + var uni = getUniversalBlock(loc.getBlock()); Preconditions.checkNotNull(uni); uni.setData(key, val); } @@ -102,7 +102,7 @@ public static void removeData(Location loc, String key) { if (block != null) { block.removeData(key); } else { - var uni = getUniversalData(loc.getBlock()); + var uni = getUniversalBlock(loc.getBlock()); Preconditions.checkNotNull(uni); uni.removeData(key); } @@ -124,7 +124,7 @@ public static void removeData(Location loc, String key) { } @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalData(UUID uuid) { + @Nullable public static SlimefunUniversalData getUniversalBlock(UUID uuid) { var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); if (uniData == null) { @@ -140,8 +140,8 @@ public static void removeData(Location loc, String key) { } @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalData(UUID uuid, Location l) { - var uniData = getUniversalData(uuid); + @Nullable public static SlimefunUniversalData getUniversalBlock(UUID uuid, Location l) { + var uniData = getUniversalBlock(uuid); if (uniData != null) { uniData.setLastPresent(l); @@ -159,10 +159,10 @@ public static void removeData(Location loc, String key) { * @return {@link SlimefunUniversalData} */ @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalData(Block block) { + @Nullable public static SlimefunUniversalData getUniversalBlock(Block block) { var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); - return uuid.map(uniId -> getUniversalData(uniId, block.getLocation())).orElse(null); + return uuid.map(id -> getUniversalBlock(id, block.getLocation())).orElse(null); } /** @@ -175,7 +175,7 @@ public static void removeData(Location loc, String key) { */ @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(Block block) { - var uniData = getUniversalData(block); + var uniData = getUniversalBlock(block); if (uniData == null) { return null; @@ -208,7 +208,7 @@ public static boolean isBlockPendingRemove(@Nonnull Block block) { } if (hasUniversalBlock(block.getLocation())) { - return getUniversalData(block).isPendingRemove(); + return getUniversalBlock(block).isPendingRemove(); } return false; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java index b552f5410a..0a403632d2 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java @@ -37,7 +37,7 @@ public AndroidType getAndroidType() { @Override protected void farm(Block b, UniversalMenu menu, Block block, boolean isAdvanced) { OfflinePlayer owner = Bukkit.getOfflinePlayer( - UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); + UUID.fromString(StorageCacheUtils.getUniversalBlock(menu.getUuid(), b.getLocation(), "owner"))); if (!Slimefun.getProtectionManager().hasPermission(owner, block, Interaction.BREAK_BLOCK)) { return; } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index a8d9a8fc9c..c25da9f0f7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -76,7 +76,7 @@ protected void dig(Block b, UniversalMenu menu, Block block) { if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) { OfflinePlayer owner = Bukkit.getOfflinePlayer( - UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); + UUID.fromString(StorageCacheUtils.getUniversalBlock(menu.getUuid(), b.getLocation(), "owner"))); if (Slimefun.getProtectionManager().hasPermission(owner, block.getLocation(), Interaction.BREAK_BLOCK)) { AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); @@ -87,7 +87,8 @@ protected void dig(Block b, UniversalMenu menu, Block block) { } // We only want to break non-Slimefun blocks - if (!StorageCacheUtils.hasBlock(block.getLocation())) { + if (!StorageCacheUtils.hasBlock(block.getLocation()) + && !StorageCacheUtils.hasUniversalBlock(block.getLocation())) { breakBlock(menu, drops, block); } } @@ -101,7 +102,7 @@ protected void moveAndDig(Block b, UniversalMenu menu, BlockFace face, Block blo if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) { OfflinePlayer owner = Bukkit.getOfflinePlayer( - UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); + UUID.fromString(StorageCacheUtils.getUniversalBlock(menu.getUuid(), b.getLocation(), "owner"))); if (Slimefun.getProtectionManager().hasPermission(owner, block.getLocation(), Interaction.BREAK_BLOCK)) { AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b)); @@ -112,7 +113,8 @@ protected void moveAndDig(Block b, UniversalMenu menu, BlockFace face, Block blo } // We only want to break non-Slimefun blocks - if (!StorageCacheUtils.hasBlock(block.getLocation())) { + if (!StorageCacheUtils.hasBlock(block.getLocation()) + && !StorageCacheUtils.hasUniversalBlock(block.getLocation())) { breakBlock(menu, drops, block); move(b, face, block); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 7689df1cad..c4822c0354 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -103,7 +103,7 @@ public void init() { @Override public boolean canOpen(Block b, Player p) { - var uniData = StorageCacheUtils.getUniversalData(b); + var uniData = StorageCacheUtils.getUniversalBlock(b); Objects.requireNonNull( uniData, @@ -124,7 +124,7 @@ public boolean canOpen(Block b, Player p) { @Override public void newInstance(UniversalMenu menu, Block b) { - var uniData = StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation()); + var uniData = StorageCacheUtils.getUniversalBlock(menu.getUuid(), b.getLocation()); Objects.requireNonNull( uniData, @@ -191,7 +191,7 @@ public void onPlayerPlace(BlockPlaceEvent e) { Player p = e.getPlayer(); Block b = e.getBlock(); - var universalData = StorageCacheUtils.getUniversalData(b); + var universalData = StorageCacheUtils.getUniversalBlock(b); universalData.setData("owner", p.getUniqueId().toString()); universalData.setData("script", DEFAULT_SCRIPT); @@ -1030,7 +1030,7 @@ public void addItems(Block b, ItemStack... items) { @ParametersAreNonnullByDefault protected void move(Block from, BlockFace face, Block to) { - var uniData = StorageCacheUtils.getUniversalData(from); + var uniData = StorageCacheUtils.getUniversalBlock(from); if (uniData == null) { throw new IllegalStateException("This android doesn't have universal data! Location at " diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java index 4c601e0d6c..8329d35f4d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java @@ -55,7 +55,7 @@ protected boolean chopTree(Block b, UniversalMenu menu, BlockFace face) { log.getWorld().playEffect(log.getLocation(), Effect.STEP_SOUND, log.getType()); OfflinePlayer owner = Bukkit.getOfflinePlayer( - UUID.fromString(StorageCacheUtils.getUniversalData(menu.getUuid(), b.getLocation(), "owner"))); + UUID.fromString(StorageCacheUtils.getUniversalBlock(menu.getUuid(), b.getLocation(), "owner"))); if (Slimefun.getProtectionManager().hasPermission(owner, log.getLocation(), Interaction.BREAK_BLOCK)) { breakLog(log, b, menu, face); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index be518a77c9..0c89a65a9a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -189,7 +189,7 @@ public void onBlockBreak(BlockBreakEvent e) { var block = e.getBlock(); var blockData = StorageCacheUtils.hasBlock(block.getLocation()) ? StorageCacheUtils.getBlock(block.getLocation()) - : StorageCacheUtils.getUniversalData(block); + : StorageCacheUtils.getUniversalBlock(block); // If there is a Slimefun Block here, call our BreakEvent and, if cancelled, cancel this event // and return diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index e96fce3ab0..a14b445182 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -111,7 +111,7 @@ private void onRightClick(Player p, Block b, BlockFace face) { if (StorageCacheUtils.hasBlock(b.getLocation()) || StorageCacheUtils.hasUniversalBlock(b.getLocation())) { var data = StorageCacheUtils.hasBlock(b.getLocation()) ? StorageCacheUtils.getBlock(b.getLocation()) - : StorageCacheUtils.getUniversalData(b); + : StorageCacheUtils.getUniversalBlock(b); try { if (data.isDataLoaded()) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index 50a7c2a42f..4b225a331a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -144,7 +144,7 @@ private void openInventory(Player p, SlimefunItem item, Block clickedBlock, Play event.getInteractEvent().setCancelled(true); if (item instanceof UniversalDataSupport) { - var uniData = StorageCacheUtils.getUniversalData(clickedBlock); + var uniData = StorageCacheUtils.getUniversalBlock(clickedBlock); if (uniData == null) { return; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index b81fd2859a..c62bd84c65 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -3,7 +3,6 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; -import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.bakedlibs.dough.blocks.ChunkPosition; @@ -44,7 +43,7 @@ public class TickerTask implements Runnable { /** * This Map holds all locations of currently actively ticking universal items. */ - private final Map tickingUniversalLocations = new ConcurrentHashMap<>(); + private final Map> tickingUniversalLocations = new ConcurrentHashMap<>(); /** * This Map tracks how many bugs have occurred in a given Location . @@ -106,14 +105,14 @@ public void run() { tickChunk(entry.getKey(), tickers, new HashSet<>(entry.getValue())); } - Set> uniLoc; + Set>> uniLoc; synchronized (tickingUniversalLocations) { uniLoc = new HashSet<>(tickingUniversalLocations.entrySet()); } - for (Map.Entry entry : uniLoc) { - tickUniversalLocation(entry.getKey(), entry.getValue(), tickers); + for (Map.Entry> entry : uniLoc) { + tickChunk(entry.getKey(), tickers, new ConcurrentHashMap<>(entry.getValue())); } } @@ -150,6 +149,21 @@ private void tickChunk(ChunkPosition chunk, Set tickers, Set tickers, Map locations) { + try { + // Only continue if the Chunk is actually loaded + if (chunk.isLoaded()) { + for (Map.Entry entry : locations.entrySet()) { + tickUniversalLocation(entry.getValue(), entry.getKey(), tickers); + } + } + } catch (ArrayIndexOutOfBoundsException | NumberFormatException x) { + Slimefun.logger() + .log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk); + } + } + private void tickLocation(@Nonnull Set tickers, @Nonnull Location l) { var blockData = StorageCacheUtils.getBlock(l); if (blockData == null || !blockData.isDataLoaded() || blockData.isPendingRemove()) { @@ -193,7 +207,7 @@ private void tickLocation(@Nonnull Set tickers, @Nonnull Location l @ParametersAreNonnullByDefault private void tickUniversalLocation(UUID uuid, Location l, @Nonnull Set tickers) { - var data = StorageCacheUtils.getUniversalData(uuid); + var data = StorageCacheUtils.getUniversalBlock(uuid); var item = SlimefunItem.getById(data.getSfId()); if (item != null && item.getBlockTicker() != null) { @@ -232,19 +246,18 @@ private void tickUniversalLocation(UUID uuid, Location l, @Nonnull Set> 4, l.getBlockZ() >> 4); + + Map newValue = new ConcurrentHashMap<>(); + Map oldValue = tickingUniversalLocations.putIfAbsent(chunk, newValue); + + if (oldValue != null) { + oldValue.put(l, uuid); + } else { + newValue.put(l, uuid); + } } /** diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java index 5d5901376b..d957700847 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java @@ -1,6 +1,5 @@ package me.mrCookieSlime.Slimefun.api.inventory; -import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import java.util.UUID; import javax.annotation.Nonnull; import lombok.Getter; @@ -15,44 +14,31 @@ public class UniversalMenu extends DirtyChestMenu { @Getter private final UUID uuid; - public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, @Nonnull Location lastPresent) { super(preset); this.uuid = uuid; - preset.clone(this); - this.getContents(); - } - - public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { - super(preset); - this.uuid = uuid; - - for (int i = 0; i < contents.length; i++) { - var item = contents[i]; - if (item == null) { - continue; - } - addItem(i, item); - } - - preset.clone(this); + preset.clone(this, lastPresent); this.getContents(); } public UniversalMenu( - @Nonnull UniversalMenuPreset preset, @Nonnull SlimefunUniversalData universalData, ItemStack[] contents) { + @Nonnull UniversalMenuPreset preset, + @Nonnull UUID uuid, + @Nonnull Location lastPresent, + ItemStack[] contents) { super(preset); - this.uuid = universalData.getUUID(); + this.uuid = uuid; for (int i = 0; i < contents.length; i++) { var item = contents[i]; - if (item == null) { + if (item == null || item.getType().isAir()) { continue; } addItem(i, item); } - preset.clone(this, universalData.getLastPresent()); + preset.clone(this, lastPresent); this.getContents(); } diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java index d5e6a4f01e..3a845e5859 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java @@ -25,7 +25,7 @@ public void newInstance(@Nonnull UniversalMenu menu, @Nonnull Block b) { @Override protected void clone(@Nonnull DirtyChestMenu menu) { if (menu instanceof UniversalMenu universalMenu) { - var uniData = StorageCacheUtils.getUniversalData(universalMenu.getUuid()); + var uniData = StorageCacheUtils.getUniversalBlock(universalMenu.getUuid()); if (uniData == null) { return; From ab59c65fbcc4908019c1927d57da7d48feb56d90 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Thu, 8 Aug 2024 15:47:46 +0800 Subject: [PATCH 30/42] fix(android): fix android not update location --- .../slimefun4/api/ErrorReport.java | 48 +++++++++++++------ .../items/androids/ProgrammableAndroid.java | 8 ++-- .../listeners/DebugFishListener.java | 11 +++++ .../implementation/tasks/TickerTask.java | 36 ++++++++++++++ .../Slimefun/api/inventory/UniversalMenu.java | 4 +- 5 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java index f8038f069f..a343d7a8dd 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java @@ -81,39 +81,57 @@ public ErrorReport(T throwable, SlimefunAddon addon, Consumer print @ParametersAreNonnullByDefault public ErrorReport(T throwable, Location l, SlimefunItem item) { this(throwable, item.getAddon(), stream -> { - stream.println("Block Info:"); - stream.println(" World: " + l.getWorld().getName()); + stream.println("方块信息:"); + stream.println(" 世界: " + l.getWorld().getName()); stream.println(" X: " + l.getBlockX()); stream.println(" Y: " + l.getBlockY()); stream.println(" Z: " + l.getBlockZ()); - stream.println(" Material: " + l.getBlock().getType()); - stream.println( - " Block Data: " + l.getBlock().getBlockData().getClass().getName()); - stream.println(" State: " + l.getBlock().getState().getClass().getName()); + stream.println(" 方块类型: " + l.getBlock().getType()); + stream.println(" 方块数据: " + l.getBlock().getBlockData().getClass().getName()); + stream.println(" 状态: " + l.getBlock().getState().getClass().getName()); stream.println(); if (item.getBlockTicker() != null) { - stream.println("Ticker-Info:"); - stream.println(" Type: " + (item.getBlockTicker().isSynchronized() ? "Synchronized" : "Asynchronous")); + stream.println("Ticker 信息:"); + stream.println(" 类型: " + (item.getBlockTicker().isSynchronized() ? "同步" : "异步")); stream.println(); } if (item instanceof EnergyNetProvider) { - stream.println("Ticker-Info:"); - stream.println(" Type: Indirect (Energy Network)"); + stream.println("Ticker 信息:"); + stream.println(" 类型: 间接 (由能源网络管理)"); stream.println(); } - stream.println("Slimefun Data:"); + stream.println("Slimefun 数据:"); stream.println(" ID: " + item.getId()); var blockData = Slimefun.getDatabaseManager().getBlockDataController().getBlockData(l); + if (blockData == null) { - stream.println("Block data is not presented."); + Slimefun.getBlockDataService() + .getUniversalDataUUID(l.getBlock()) + .ifPresentOrElse( + uuid -> { + var universalData = Slimefun.getDatabaseManager() + .getBlockDataController() + .getUniversalDataFromCache(uuid); + if (universalData != null) { + stream.println(" 数据加载状态: " + universalData.isDataLoaded()); + stream.println(" 物品栏: " + (universalData.getUniversalMenu() != null)); + stream.println(" 数据: "); + universalData + .getAllData() + .forEach((k, v) -> stream.println(" " + k + ": " + v)); + } else { + stream.println("该方块没有任何数据."); + } + }, + () -> stream.println("该方块没有任何数据.")); } else { - stream.println(" Is data loaded: " + blockData.isDataLoaded()); - stream.println(" Inventory: " + (blockData.getBlockMenu() != null)); - stream.println(" Data: "); + stream.println(" 数据加载状态: " + blockData.isDataLoaded()); + stream.println(" 物品栏: " + (blockData.getBlockMenu() != null)); + stream.println(" 数据: "); blockData.getAllData().forEach((k, v) -> stream.println(" " + k + ": " + v)); } stream.println(); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index c4822c0354..716debb60a 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -830,8 +830,7 @@ protected void tick(Block b, SlimefunUniversalData data) { Instruction instruction = Instruction.getInstruction(script[index]); if (instruction == null) { - Slimefun.instance() - .getLogger() + Slimefun.logger() .log( Level.WARNING, "Failed to parse Android instruction: {0}, maybe your server is out of date?", @@ -1059,6 +1058,9 @@ protected void move(Block from, BlockFace face, Block to) { } })); + Slimefun.getBlockDataService() + .setUniversalDataUUID(to, uniData.getUUID().toString()); + Slimefun.runSync(() -> { PlayerSkin skin = PlayerSkin.fromBase64(texture); Material type = to.getType(); @@ -1070,7 +1072,7 @@ protected void move(Block from, BlockFace face, Block to) { from.setType(Material.AIR); uniData.setLastPresent(to.getLocation()); - uniData.getUniversalMenu().update(); + uniData.getUniversalMenu().update(to.getLocation()); Slimefun.getTickerTask().enableTicker(uniData.getUUID(), to.getLocation()); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index a14b445182..ef5d0891e4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -220,6 +220,17 @@ private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { p.sendMessage(ChatColors.color("&dTicker: " + redCross)); } + Slimefun.getTickerTask().getLocations(p.getLocation().getChunk()).stream() + .filter(l -> l.equals(b.getLocation())) + .findFirst() + .ifPresent(tickLoc -> p.sendMessage(ChatColors.color("&dIn Ticker Queue: " + greenCheckmark))); + + Slimefun.getTickerTask().getUniversalLocations(p.getLocation().getChunk()).entrySet().stream() + .filter(entry -> entry.getKey().equals(b.getLocation())) + .findFirst() + .ifPresent( + tickLoc -> p.sendMessage(ChatColors.color("&dIn Ticker Queue (Universal): " + greenCheckmark))); + if (Slimefun.getProfiler().hasTimings(b)) { p.sendMessage( ChatColors.color(" &dTimings: &e" + Slimefun.getProfiler().getTime(b))); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index c62bd84c65..706e524f37 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -8,6 +8,7 @@ import io.github.bakedlibs.dough.blocks.ChunkPosition; import io.github.thebusybiscuit.slimefun4.api.ErrorReport; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; +import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.Collections; import java.util.HashSet; @@ -340,6 +341,41 @@ public Set getLocations(@Nonnull Chunk chunk) { return Collections.unmodifiableSet(locations); } + /** + * 返回一个 只读 的 {@link Map} + * 代表每个 {@link ChunkPosition} 中有 {@link UniversalDataSupport} 属性的物品 + * Tick 的 {@link Location 位置}集合. + * + * 其中包含的 {@link Location} 可以是已加载或卸载的 {@link Chunk} + * + * @return 包含所有通用机器 Tick {@link Location 位置}的只读 {@link Map} + */ + @Nonnull + public Map> getUniversalLocations() { + return Collections.unmodifiableMap(tickingUniversalLocations); + } + + /** + * 返回一个给定区块下的 只读 的 {@link Map} + * 代表每个 {@link ChunkPosition} 中有 {@link UniversalDataSupport} 属性的物品 + * Tick 的 {@link Location 位置}集合. + * + * 其中包含的 {@link Location} 可以是已加载或卸载的 {@link Chunk} + * + * @param chunk + * {@link Chunk} + * + * @return 包含所有通用机器 Tick {@link Location 位置}的只读 {@link Map} + */ + @Nonnull + public Map getUniversalLocations(@Nonnull Chunk chunk) { + Validate.notNull(chunk, "The Chunk cannot be null!"); + + Map locations = + tickingUniversalLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptyMap()); + return Collections.unmodifiableMap(locations); + } + /** * This enables the ticker at the given {@link Location} and adds it to our "queue". * diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java index d957700847..e469f7852e 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java +++ b/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java @@ -42,8 +42,8 @@ public UniversalMenu( this.getContents(); } - public void update() { - preset.clone(this); + public void update(@Nonnull Location lastPresent) { + ((UniversalMenuPreset) preset).clone(this, lastPresent); } /** From 2624b453487fbbabf5a13718d9a6b7a8a70ed006 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 15 Sep 2024 16:52:05 +0800 Subject: [PATCH 31/42] fix: refill missing method --- .../slimefun4/implementation/Slimefun.java | 3 -- .../implementation/tasks/TickerTask.java | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java index 7df9f41651..fde30a5094 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/Slimefun.java @@ -315,9 +315,6 @@ private void onPluginStart() { cfgManager.load(); registry.load(this); - // Inject downstream extra staff - SlimefunExtended.register(this); - logger.log(Level.INFO, "正在加载数据库..."); if (PlayerProfileMigrator.getInstance().hasOldData() || BlockStorageMigrator.getInstance().hasOldData()) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index 1d3eede665..2ddcfe8dfb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -410,6 +411,36 @@ public void enableTicker(@Nonnull Location l) { } } + /** + * This enables the ticker at the given {@link Location} and adds it to our "queue". + * + * @param uuid + * The {@link UUID} to activate + */ + public void enableTicker(@Nonnull UUID uuid, @Nonnull Location l) { + Validate.notNull(uuid, "UUID cannot be null!"); + Validate.notNull(l, "Location cannot be null!"); + + synchronized (tickingUniversalLocations) { + ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); + + /* + Note that all the values in #tickingLocations must be thread-safe. + Thus, the choice is between the CHM KeySet or a synchronized set. + The CHM KeySet was chosen since it at least permits multiple concurrent + reads without blocking. + */ + Map newValue = new ConcurrentHashMap<>(); + Map oldValue = tickingUniversalLocations.putIfAbsent(chunk, newValue); + + /** + * This is faster than doing computeIfAbsent(...) + * on a ConcurrentHashMap because it won't block the Thread for too long + */ + Objects.requireNonNullElse(oldValue, newValue).put(l, uuid); + } + } + /** * This method disables the ticker at the given {@link Location} and removes it from our internal * "queue". From dcf7f0355d2fd38ccc01967e4e5b8a3f8898692a Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 15 Sep 2024 17:43:40 +0800 Subject: [PATCH 32/42] refactor: rework on tickertask storage --- .../controller/BlockDataController.java | 10 +- .../slimefun4/core/ticker/TickLocation.java | 32 ++++ .../items/androids/ProgrammableAndroid.java | 4 +- .../listeners/DebugFishListener.java | 12 +- .../implementation/tasks/TickerTask.java | 149 ++++++------------ 5 files changed, 94 insertions(+), 113 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 9982769f16..9c75627e40 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -311,11 +311,11 @@ public void removeBlock(Location l) { var removed = getChunkDataCache(l.getChunk(), true).removeBlockData(l); if (removed == null) { - getUniversalDataFromCache(l).ifPresentOrElse(data -> removeUniversalData(data.getUUID()), () -> { + getUniversalDataFromCache(l).ifPresentOrElse(data -> removeUniversalData(l, data.getUUID()), () -> { if (Bukkit.isPrimaryThread()) { Slimefun.getBlockDataService() .getUniversalDataUUID(l.getBlock()) - .ifPresent(this::removeUniversalData); + .ifPresent(uuid -> removeUniversalData(l, uuid)); } }); @@ -336,7 +336,7 @@ public void removeBlock(Location l) { } } - public void removeUniversalData(UUID uuid) { + public void removeUniversalData(Location lastPresent, UUID uuid) { checkDestroy(); var toRemove = loadedUniversalData.get(uuid); @@ -358,7 +358,7 @@ public void removeUniversalData(UUID uuid) { } if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { - Slimefun.getTickerTask().disableTicker(uuid); + Slimefun.getTickerTask().disableTicker(lastPresent); } } @@ -780,7 +780,7 @@ public void loadUniversalData(SlimefunUniversalData uniData) { if (sfItem != null && sfItem.isTicking()) { if (!uniData.getLastPresent().getBlock().getType().isAir()) { - Slimefun.getTickerTask().enableTicker(uniData.getUUID(), uniData.getLastPresent()); + Slimefun.getTickerTask().enableTicker(uniData.getLastPresent(), uniData.getUUID()); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java new file mode 100644 index 0000000000..c7d5ef9693 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java @@ -0,0 +1,32 @@ +package io.github.thebusybiscuit.slimefun4.core.ticker; + +import io.github.bakedlibs.dough.blocks.BlockPosition; + +import java.util.UUID; + +import lombok.Getter; +import org.bukkit.Location; + +@Getter +public class TickLocation { + private final BlockPosition position; + private final UUID uuid; + + public TickLocation(BlockPosition position) { + this.position = position; + uuid = null; + } + + public TickLocation(BlockPosition position, UUID uuid) { + this.position = position; + this.uuid = uuid; + } + + public boolean isUniversal() { + return uuid != null; + } + + public Location getLocation() { + return position.toLocation(); + } +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 716debb60a..4b6bec69ff 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -1050,7 +1050,7 @@ protected void move(Block from, BlockFace face, Block to) { return; } - Slimefun.getTickerTask().disableTicker(uniData.getUUID()); + Slimefun.getTickerTask().disableTicker(from.getLocation()); to.setBlockData(Material.PLAYER_HEAD.createBlockData(data -> { if (data instanceof Rotatable rotatable) { @@ -1074,7 +1074,7 @@ protected void move(Block from, BlockFace face, Block to) { uniData.setLastPresent(to.getLocation()); uniData.getUniversalMenu().update(to.getLocation()); - Slimefun.getTickerTask().enableTicker(uniData.getUUID(), to.getLocation()); + Slimefun.getTickerTask().enableTicker(to.getLocation(), uniData.getUUID()); } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index ef5d0891e4..168b28fab6 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -220,16 +220,10 @@ private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { p.sendMessage(ChatColors.color("&dTicker: " + redCross)); } - Slimefun.getTickerTask().getLocations(p.getLocation().getChunk()).stream() - .filter(l -> l.equals(b.getLocation())) + Slimefun.getTickerTask().getTickLocations(p.getLocation().getChunk()).stream() + .filter(l -> l.getLocation().equals(b.getLocation())) .findFirst() - .ifPresent(tickLoc -> p.sendMessage(ChatColors.color("&dIn Ticker Queue: " + greenCheckmark))); - - Slimefun.getTickerTask().getUniversalLocations(p.getLocation().getChunk()).entrySet().stream() - .filter(entry -> entry.getKey().equals(b.getLocation())) - .findFirst() - .ifPresent( - tickLoc -> p.sendMessage(ChatColors.color("&dIn Ticker Queue (Universal): " + greenCheckmark))); + .ifPresent(tickLoc -> p.sendMessage(ChatColors.color("&dIn Ticker Queue " + (tickLoc.isUniversal() ? "(Universal)" : "") + ": " + greenCheckmark))); if (Slimefun.getProfiler().hasTimings(b)) { p.sendMessage( diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index 2ddcfe8dfb..878796cab8 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -9,6 +9,7 @@ import io.github.thebusybiscuit.slimefun4.api.ErrorReport; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; +import io.github.thebusybiscuit.slimefun4.core.ticker.TickLocation; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.Collections; import java.util.HashSet; @@ -18,7 +19,9 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; +import java.util.stream.Collectors; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; import org.apache.commons.lang.Validate; @@ -41,12 +44,7 @@ public class TickerTask implements Runnable { * This Map holds all currently actively ticking locations. * The value of this map (Set entries) MUST be thread-safe and mutable. */ - private final Map> tickingLocations = new ConcurrentHashMap<>(); - - /** - * This Map holds all locations of currently actively ticking universal items. - */ - private final Map> tickingUniversalLocations = new ConcurrentHashMap<>(); + private final Map> tickingLocations = new ConcurrentHashMap<>(); /** * This Map tracks how many bugs have occurred in a given Location . @@ -98,25 +96,15 @@ public void run() { // Run our ticker code if (!halted) { - Set>> loc; + Set>> loc; synchronized (tickingLocations) { loc = new HashSet<>(tickingLocations.entrySet()); } - for (Map.Entry> entry : loc) { + for (Map.Entry> entry : loc) { tickChunk(entry.getKey(), tickers, new HashSet<>(entry.getValue())); } - - Set>> uniLoc; - - synchronized (tickingUniversalLocations) { - uniLoc = new HashSet<>(tickingUniversalLocations.entrySet()); - } - - for (Map.Entry> entry : uniLoc) { - tickChunk(entry.getKey(), tickers, new ConcurrentHashMap<>(entry.getValue())); - } } // Start a new tick cycle for every BlockTicker @@ -138,27 +126,16 @@ public void run() { } @ParametersAreNonnullByDefault - private void tickChunk(ChunkPosition chunk, Set tickers, Set locations) { - try { - // Only continue if the Chunk is actually loaded - if (chunk.isLoaded()) { - for (Location l : locations) { - tickLocation(tickers, l); - } - } - } catch (ArrayIndexOutOfBoundsException | NumberFormatException x) { - Slimefun.logger() - .log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk); - } - } - - @ParametersAreNonnullByDefault - private void tickChunk(ChunkPosition chunk, Set tickers, Map locations) { + private void tickChunk(ChunkPosition chunk, Set tickers, Set locations) { try { // Only continue if the Chunk is actually loaded if (chunk.isLoaded()) { - for (Map.Entry entry : locations.entrySet()) { - tickUniversalLocation(entry.getValue(), entry.getKey(), tickers); + for (TickLocation l : locations) { + if (l.isUniversal()) { + tickUniversalLocation(l.getUuid(), l.getLocation(), tickers); + } else { + tickLocation(tickers, l.getLocation()); + } } } } catch (ArrayIndexOutOfBoundsException | NumberFormatException x) { @@ -310,6 +287,22 @@ public int getTickRate() { return tickRate; } + /** + * BINARY COMPATIBILITY + * + * Use #getTickLocations instead + * + * @return A {@link Map} representation of all ticking {@link Location Locations} + */ + @Nonnull + public Map> getLocations() { + return tickingLocations.entrySet().stream().collect( + Collectors.toMap( + Map.Entry::getKey, + e -> e.getValue().stream().map(TickLocation::getLocation + ).collect(Collectors.toUnmodifiableSet()))); + } + /** * This method returns a read-only {@link Map} * representation of every {@link ChunkPosition} and its corresponding @@ -317,10 +310,10 @@ public int getTickRate() { * * This does include any {@link Location} from an unloaded {@link Chunk} too! * - * @return A {@link Map} representation of all ticking {@link Location Locations} + * @return A {@link Map} representation of all ticking {@link TickLocation Locations} */ @Nonnull - public Map> getLocations() { + public Map> getTickLocations() { return Collections.unmodifiableMap(tickingLocations); } @@ -339,22 +332,8 @@ public Map> getLocations() { public Set getLocations(@Nonnull Chunk chunk) { Validate.notNull(chunk, "The Chunk cannot be null!"); - Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptySet()); - return Collections.unmodifiableSet(locations); - } - - /** - * 返回一个 只读 的 {@link Map} - * 代表每个 {@link ChunkPosition} 中有 {@link UniversalDataSupport} 属性的物品 - * Tick 的 {@link Location 位置}集合. - * - * 其中包含的 {@link Location} 可以是已加载或卸载的 {@link Chunk} - * - * @return 包含所有通用机器 Tick {@link Location 位置}的只读 {@link Map} - */ - @Nonnull - public Map> getUniversalLocations() { - return Collections.unmodifiableMap(tickingUniversalLocations); + Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptySet()); + return locations.stream().map(TickLocation::getLocation).collect(Collectors.toUnmodifiableSet()); } /** @@ -367,15 +346,13 @@ public Map> getUniversalLocations() { * @param chunk * {@link Chunk} * - * @return 包含所有通用机器 Tick {@link Location 位置}的只读 {@link Map} + * @return 包含所有机器 Tick {@link TickLocation 位置}的只读 {@link Map} */ @Nonnull - public Map getUniversalLocations(@Nonnull Chunk chunk) { + public Set getTickLocations(@Nonnull Chunk chunk) { Validate.notNull(chunk, "The Chunk cannot be null!"); - Map locations = - tickingUniversalLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptyMap()); - return Collections.unmodifiableMap(locations); + return tickingLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptySet()); } /** @@ -385,10 +362,15 @@ public Map getUniversalLocations(@Nonnull Chunk chunk) { * The {@link Location} to activate */ public void enableTicker(@Nonnull Location l) { + enableTicker(l, null); + } + + public void enableTicker(@Nonnull Location l, @Nullable UUID uuid) { Validate.notNull(l, "Location cannot be null!"); synchronized (tickingLocations) { ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); + final var tickPosition = uuid == null ? new TickLocation(new BlockPosition(l)) : new TickLocation(new BlockPosition(l), uuid); /* Note that all the values in #tickingLocations must be thread-safe. @@ -396,51 +378,21 @@ public void enableTicker(@Nonnull Location l) { The CHM KeySet was chosen since it at least permits multiple concurrent reads without blocking. */ - Set newValue = ConcurrentHashMap.newKeySet(); - Set oldValue = tickingLocations.putIfAbsent(chunk, newValue); + Set newValue = ConcurrentHashMap.newKeySet(); + Set oldValue = tickingLocations.putIfAbsent(chunk, newValue); /** * This is faster than doing computeIfAbsent(...) * on a ConcurrentHashMap because it won't block the Thread for too long */ if (oldValue != null) { - oldValue.add(l); + oldValue.add(tickPosition); } else { - newValue.add(l); + newValue.add(tickPosition); } } } - /** - * This enables the ticker at the given {@link Location} and adds it to our "queue". - * - * @param uuid - * The {@link UUID} to activate - */ - public void enableTicker(@Nonnull UUID uuid, @Nonnull Location l) { - Validate.notNull(uuid, "UUID cannot be null!"); - Validate.notNull(l, "Location cannot be null!"); - - synchronized (tickingUniversalLocations) { - ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); - - /* - Note that all the values in #tickingLocations must be thread-safe. - Thus, the choice is between the CHM KeySet or a synchronized set. - The CHM KeySet was chosen since it at least permits multiple concurrent - reads without blocking. - */ - Map newValue = new ConcurrentHashMap<>(); - Map oldValue = tickingUniversalLocations.putIfAbsent(chunk, newValue); - - /** - * This is faster than doing computeIfAbsent(...) - * on a ConcurrentHashMap because it won't block the Thread for too long - */ - Objects.requireNonNullElse(oldValue, newValue).put(l, uuid); - } - } - /** * This method disables the ticker at the given {@link Location} and removes it from our internal * "queue". @@ -453,10 +405,10 @@ public void disableTicker(@Nonnull Location l) { synchronized (tickingLocations) { ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); - Set locations = tickingLocations.get(chunk); + Set locations = tickingLocations.get(chunk); if (locations != null) { - locations.remove(l); + locations.removeIf(tk -> l.equals(tk.getLocation())); if (locations.isEmpty()) { tickingLocations.remove(chunk); @@ -469,14 +421,17 @@ public void disableTicker(@Nonnull Location l) { * This method disables the ticker at the given {@link UUID} and removes it from our internal * "queue". * + * DO NOT USE THIS until you cannot disable by location, + * or enjoy extremely slow. + * * @param uuid * The {@link UUID} to remove */ public void disableTicker(@Nonnull UUID uuid) { Validate.notNull(uuid, "Universal Data ID cannot be null!"); - synchronized (tickingUniversalLocations) { - tickingUniversalLocations.remove(uuid); + synchronized (tickingLocations) { + tickingLocations.values().forEach(loc -> loc.removeIf(tk -> uuid.equals(tk.getUuid()))); } } From 850953d248456132a1c883e795d197d1fc3676e0 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 15 Sep 2024 17:57:14 +0800 Subject: [PATCH 33/42] chore: spotless --- .../slimefun4/core/ticker/TickLocation.java | 2 -- .../listeners/DebugFishListener.java | 3 ++- .../slimefun4/implementation/tasks/TickerTask.java | 14 +++++++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java index c7d5ef9693..df4e3b5f62 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/ticker/TickLocation.java @@ -1,9 +1,7 @@ package io.github.thebusybiscuit.slimefun4.core.ticker; import io.github.bakedlibs.dough.blocks.BlockPosition; - import java.util.UUID; - import lombok.Getter; import org.bukkit.Location; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index 168b28fab6..1bcedc901b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -223,7 +223,8 @@ private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { Slimefun.getTickerTask().getTickLocations(p.getLocation().getChunk()).stream() .filter(l -> l.getLocation().equals(b.getLocation())) .findFirst() - .ifPresent(tickLoc -> p.sendMessage(ChatColors.color("&dIn Ticker Queue " + (tickLoc.isUniversal() ? "(Universal)" : "") + ": " + greenCheckmark))); + .ifPresent(tickLoc -> p.sendMessage(ChatColors.color( + "&dIn Ticker Queue " + (tickLoc.isUniversal() ? "(Universal)" : "") + ": " + greenCheckmark))); if (Slimefun.getProfiler().hasTimings(b)) { p.sendMessage( diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index 878796cab8..af6d1eb91d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -14,7 +14,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -296,11 +295,10 @@ public int getTickRate() { */ @Nonnull public Map> getLocations() { - return tickingLocations.entrySet().stream().collect( - Collectors.toMap( - Map.Entry::getKey, - e -> e.getValue().stream().map(TickLocation::getLocation - ).collect(Collectors.toUnmodifiableSet()))); + return tickingLocations.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream() + .map(TickLocation::getLocation) + .collect(Collectors.toUnmodifiableSet()))); } /** @@ -370,7 +368,9 @@ public void enableTicker(@Nonnull Location l, @Nullable UUID uuid) { synchronized (tickingLocations) { ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); - final var tickPosition = uuid == null ? new TickLocation(new BlockPosition(l)) : new TickLocation(new BlockPosition(l), uuid); + final var tickPosition = uuid == null + ? new TickLocation(new BlockPosition(l)) + : new TickLocation(new BlockPosition(l), uuid); /* Note that all the values in #tickingLocations must be thread-safe. From b439401b6838de2c042d274dbadd960cadc12d88 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 14 Oct 2024 11:14:11 +0800 Subject: [PATCH 34/42] refactor: use BlockPosition in ticker --- pom.xml | 7 +++++++ .../java/city/norain/slimefun4/SlimefunExtended.java | 8 ++++++++ .../storage/controller/BlockDataController.java | 7 ++++--- .../storage/controller/SlimefunUniversalData.java | 11 ++++++++--- .../plugin/slimefun4/storage/migrator/IMigrator.java | 4 +++- .../core/config/SlimefunDatabaseManager.java | 3 --- .../items/autocrafters/SlimefunAutoCrafter.java | 1 - 7 files changed, 30 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 6ae207cb15..bea41c2928 100644 --- a/pom.xml +++ b/pom.xml @@ -265,6 +265,13 @@ provided + + org.apache.logging.log4j + log4j-core + 2.24.1 + provided + + com.github.StarWishsama.dough diff --git a/src/main/java/city/norain/slimefun4/SlimefunExtended.java b/src/main/java/city/norain/slimefun4/SlimefunExtended.java index 030854eb09..7985f3d483 100644 --- a/src/main/java/city/norain/slimefun4/SlimefunExtended.java +++ b/src/main/java/city/norain/slimefun4/SlimefunExtended.java @@ -2,12 +2,16 @@ import city.norain.slimefun4.compatibillty.VersionedEvent; import city.norain.slimefun4.listener.SlimefunMigrateListener; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.pool.HikariPool; import io.github.bakedlibs.dough.versions.MinecraftVersion; import io.github.bakedlibs.dough.versions.UnknownServerVersionException; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.logging.Level; import javax.annotation.Nonnull; import lombok.Getter; +import org.apache.logging.log4j.core.config.Configurator; public final class SlimefunExtended { private static SlimefunMigrateListener migrateListener = new SlimefunMigrateListener(); @@ -23,6 +27,10 @@ private static void checkDebug() { databaseDebugMode = true; Slimefun.getSQLProfiler().start(); + } else { + Configurator.setLevel(HikariConfig.class.getName(), org.apache.logging.log4j.Level.OFF); + Configurator.setLevel(HikariDataSource.class.getName(), org.apache.logging.log4j.Level.OFF); + Configurator.setLevel(HikariPool.class.getName(), org.apache.logging.log4j.Level.OFF); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 9c75627e40..b91d90a0fc 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -15,6 +15,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.util.DataUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.InvStorageUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; +import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.bakedlibs.dough.collections.Pair; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; @@ -250,7 +251,7 @@ public SlimefunUniversalData createUniversalData(Location l, String sfId) { checkDestroy(); var uuid = UUID.randomUUID(); - var uniData = new SlimefunUniversalData(uuid, l, sfId); + var uniData = new SlimefunUniversalData(uuid, new BlockPosition(l), sfId); uniData.setIsDataLoaded(true); @@ -459,7 +460,7 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { ? null : new SlimefunUniversalData( uuid, - LocationUtils.toLocation(result.get(0).get(FieldKey.LAST_PRESENT)), + new BlockPosition(LocationUtils.toLocation(result.get(0).get(FieldKey.LAST_PRESENT))), result.get(0).get(FieldKey.SLIMEFUN_ID)); } @@ -655,7 +656,7 @@ public void loadUniversalData() { var uuid = data.getUUID(FieldKey.UNIVERSAL_UUID); var location = LocationUtils.toLocation(data.get(FieldKey.LAST_PRESENT)); - var uniData = new SlimefunUniversalData(uuid, location, sfId); + var uniData = new SlimefunUniversalData(uuid, new BlockPosition(location), sfId); scheduleReadTask(() -> loadUniversalData(uniData)); }); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index f247495c56..52aad69ef4 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -1,5 +1,6 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; +import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.UUID; import javax.annotation.Nullable; @@ -15,18 +16,18 @@ public class SlimefunUniversalData extends ASlimefunDataContainer { private volatile UniversalMenu universalMenu; - @Nullable private volatile Location lastPresent; + @Nullable private volatile BlockPosition lastPresent; private volatile boolean pendingRemove = false; @ParametersAreNonnullByDefault - SlimefunUniversalData(UUID uuid, Location location, String sfId) { + SlimefunUniversalData(UUID uuid, BlockPosition location, String sfId) { super(uuid.toString(), sfId); this.lastPresent = location; } @ParametersAreNonnullByDefault - SlimefunUniversalData(UUID uuid, Location location, SlimefunUniversalData other) { + SlimefunUniversalData(UUID uuid, BlockPosition location, SlimefunUniversalData other) { super(uuid.toString(), other, other.getSfId()); this.lastPresent = location; } @@ -66,6 +67,10 @@ public UUID getUUID() { return UUID.fromString(getKey()); } + public Location getLastPresent() { + return this.lastPresent.toLocation(); + } + @Override public String toString() { return "SlimefunUniversalData [sfId=" + getSfId() + ", isPendingRemove=" + pendingRemove + "]"; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/IMigrator.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/IMigrator.java index 8048c6d810..20a1543531 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/IMigrator.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/IMigrator.java @@ -5,5 +5,7 @@ public interface IMigrator { MigrateStatus migrateData(); - String getName(); + default String getName() { + return this.getClass().getSimpleName(); + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/config/SlimefunDatabaseManager.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/config/SlimefunDatabaseManager.java index 805bd4387f..757b0ed886 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/config/SlimefunDatabaseManager.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/config/SlimefunDatabaseManager.java @@ -49,9 +49,6 @@ public SlimefunDatabaseManager(Slimefun plugin) { public void init() { initDefaultVal(); - // Minimise hikari log - System.setProperty("org.slf4j.simpleLogger.log.com.zaxxer.hikari", "error"); - try { blockDataStorageType = StorageType.valueOf(blockStorageConfig.getString("storageType")); var readExecutorThread = blockStorageConfig.getInt("readExecutorThread"); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java index 3a9210f64a..c1587cb33b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java @@ -116,7 +116,6 @@ protected void updateRecipe(@Nonnull Block b, @Nonnull Player p) { menu.open(p); SoundEffect.AUTO_CRAFTER_UPDATE_RECIPE.playAt(b); - ; if (!task.isEmpty()) { task.start(menu.toInventory()); From b7a8d51e0f4b125bcd154e41a25b6947a386ebe9 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 14 Oct 2024 16:38:56 +0800 Subject: [PATCH 35/42] feat: migrate android machine data --- .../controller/BlockDataController.java | 68 +++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index b91d90a0fc..857e5ae151 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -337,6 +337,25 @@ public void removeBlock(Location l) { } } + public void removeBlockData(Location l) { + checkDestroy(); + + var removed = getChunkDataCache(l.getChunk(), true).removeBlockData(l); + + if (removed == null || !removed.isDataLoaded()) { + return; + } + + var menu = removed.getBlockMenu(); + if (menu != null) { + InventoryUtil.closeInventory(menu.toInventory()); + } + + if (Slimefun.getRegistry().getTickerBlocks().contains(removed.getSfId())) { + Slimefun.getTickerTask().disableTicker(l); + } + } + public void removeUniversalData(Location lastPresent, UUID uuid) { checkDestroy(); @@ -702,12 +721,18 @@ public void loadBlockData(SlimefunBlockData blockData) { return; } + var sfItem = SlimefunItem.getById(blockData.getSfId()); + var universal = sfItem instanceof UniversalDataSupport; + getData(key) .forEach(recordSet -> blockData.setCacheInternal( recordSet.get(FieldKey.DATA_KEY), DataUtils.blockDataDebase64(recordSet.get(FieldKey.DATA_VALUE)), false)); - blockData.setIsDataLoaded(true); + + if (!universal) { + blockData.setIsDataLoaded(true); + } var menuPreset = BlockMenuPreset.getPreset(blockData.getSfId()); if (menuPreset != null) { @@ -724,15 +749,19 @@ public void loadBlockData(SlimefunBlockData blockData) { blockData.setBlockMenu(new BlockMenu(menuPreset, blockData.getLocation(), inv)); var content = blockData.getMenuContents(); - if (content != null) { + if (content != null && !universal) { invSnapshots.put(blockData.getKey(), InvStorageUtils.getInvSnapshot(content)); } } - var sfItem = SlimefunItem.getById(blockData.getSfId()); - if (sfItem != null && sfItem.isTicking()) { + if (!universal && sfItem != null && sfItem.isTicking()) { Slimefun.getTickerTask().enableTicker(blockData.getLocation()); } + + // Universal data migration process + if (universal) { + migrateUniversalData(blockData); + } } finally { lock.unlock(key); } @@ -1204,4 +1233,35 @@ private void clearBlockCacheAndTasks(SlimefunBlockData blockData) { removeDelayedBlockDataUpdates(scopeKey); abortScopeTask(scopeKey); } + + private void migrateUniversalData(@Nonnull SlimefunBlockData blockData) { + try { + if (blockData == null || !blockData.isDataLoaded() || blockData.isPendingRemove()) { + return; + } + + var universalData = createUniversalData(blockData.getLocation(), blockData.getSfId()); + + universalData.setLastPresent(new BlockPosition(blockData.getLocation())); + + for (Map.Entry entry : blockData.getAllData().entrySet()) { + universalData.setData(entry.getKey(), entry.getValue()); + } + + final var oldMenu = blockData.getBlockMenu().getContents(); + final var newMenu = universalData.getUniversalMenu(); + + for (int slot = 0; slot < oldMenu.length; slot++) { + if (newMenu.getPreset().getPresetSlots().contains(slot)) { + continue; + } + + newMenu.addItem(slot, oldMenu[slot]); + } + + removeBlockData(blockData.getLocation()); + } catch (Exception e) { + Slimefun.logger().log(Level.WARNING, "迁移机器人数据时出现错误", e); + } + } } From 09ff45e6e904b985f2d2679d5ebc9ea44bbc8cc8 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Mon, 14 Oct 2024 16:41:13 +0800 Subject: [PATCH 36/42] chore: add docs --- .../slimefun4/storage/controller/BlockDataController.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 857e5ae151..82d709bc7f 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -1234,6 +1234,11 @@ private void clearBlockCacheAndTasks(SlimefunBlockData blockData) { abortScopeTask(scopeKey); } + /** + * 迁移旧 Slimefun 机器数据至通用数据 + * + * @param blockData + */ private void migrateUniversalData(@Nonnull SlimefunBlockData blockData) { try { if (blockData == null || !blockData.isDataLoaded() || blockData.isPendingRemove()) { From 29009af21473064ec505c4ceb52252e7b90554a2 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 20 Oct 2024 09:38:29 +0800 Subject: [PATCH 37/42] fix: merge follow up fix --- .../slimefun4/storage/controller/BlockDataController.java | 1 + .../mc/plugin/slimefun4/storage/util/StorageCacheUtils.java | 5 +++-- .../implementation/items/androids/ProgrammableAndroid.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index df3f8b0f37..894ca03d33 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -1,5 +1,6 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; +import city.norain.slimefun4.utils.InventoryUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.IDataSourceAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.common.DataScope; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 79a9575e6a..57df8ef797 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -6,6 +6,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.HashSet; @@ -144,7 +145,7 @@ public static void removeData(Location loc, String key) { var uniData = getUniversalBlock(uuid); if (uniData != null) { - uniData.setLastPresent(l); + uniData.setLastPresent(new BlockPosition(l)); } return uniData; @@ -197,7 +198,7 @@ public static void removeData(Location loc, String key) { return null; } - uniData.setLastPresent(l); + uniData.setLastPresent(new BlockPosition(l)); return uniData.getUniversalMenu(); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index 4b6bec69ff..b6f5787253 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -3,6 +3,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; +import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.bakedlibs.dough.chat.ChatInput; import io.github.bakedlibs.dough.common.ChatColors; import io.github.bakedlibs.dough.common.CommonPatterns; @@ -1071,7 +1072,7 @@ protected void move(Block from, BlockFace face, Block to) { }); from.setType(Material.AIR); - uniData.setLastPresent(to.getLocation()); + uniData.setLastPresent(new BlockPosition(to.getLocation())); uniData.getUniversalMenu().update(to.getLocation()); Slimefun.getTickerTask().enableTicker(to.getLocation(), uniData.getUUID()); From d9deb08c22112406f676d3b2508d3c3cc9adafdd Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sun, 20 Oct 2024 12:23:41 +0800 Subject: [PATCH 38/42] feat: complete android data migration --- .../controller/BlockDataController.java | 119 ++++++++++-------- 1 file changed, 67 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 894ca03d33..0440f1defd 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -380,6 +380,8 @@ public void removeUniversalData(Location lastPresent, UUID uuid) { if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { Slimefun.getTickerTask().disableTicker(lastPresent); } + + loadedUniversalData.remove(uuid); } void removeBlockDirectly(Location l) { @@ -731,44 +733,45 @@ public void loadBlockData(SlimefunBlockData blockData) { var sfItem = SlimefunItem.getById(blockData.getSfId()); var universal = sfItem instanceof UniversalDataSupport; - getData(key) - .forEach(recordSet -> blockData.setCacheInternal( - recordSet.get(FieldKey.DATA_KEY), - DataUtils.blockDataDebase64(recordSet.get(FieldKey.DATA_VALUE)), - false)); + var kvData = getData(key); + + var menuKey = new RecordKey(DataScope.BLOCK_INVENTORY); + menuKey.addCondition(FieldKey.LOCATION, blockData.getKey()); + menuKey.addField(FieldKey.INVENTORY_SLOT); + menuKey.addField(FieldKey.INVENTORY_ITEM); + + var invData = getData(menuKey); + + if (universal) { + migrateUniversalData(blockData.getLocation(), blockData.getSfId(), kvData, invData); + } else { + kvData.forEach(recordSet -> blockData.setCacheInternal( + recordSet.get(FieldKey.DATA_KEY), + DataUtils.blockDataDebase64(recordSet.get(FieldKey.DATA_VALUE)), + false)); - if (!universal) { blockData.setIsDataLoaded(true); - } - var menuPreset = BlockMenuPreset.getPreset(blockData.getSfId()); - if (menuPreset != null) { - var menuKey = new RecordKey(DataScope.BLOCK_INVENTORY); - menuKey.addCondition(FieldKey.LOCATION, blockData.getKey()); - menuKey.addField(FieldKey.INVENTORY_SLOT); - menuKey.addField(FieldKey.INVENTORY_ITEM); + var menuPreset = BlockMenuPreset.getPreset(blockData.getSfId()); - var inv = new ItemStack[54]; - getData(menuKey) - .forEach(record -> inv[record.getInt(FieldKey.INVENTORY_SLOT)] = - record.getItemStack(FieldKey.INVENTORY_ITEM)); + if (menuPreset != null) { + var inv = new ItemStack[54]; - blockData.setBlockMenu(new BlockMenu(menuPreset, blockData.getLocation(), inv)); + invData.forEach(record -> + inv[record.getInt(FieldKey.INVENTORY_SLOT)] = record.getItemStack(FieldKey.INVENTORY_ITEM)); - var content = blockData.getMenuContents(); - if (content != null && !universal) { - invSnapshots.put(blockData.getKey(), InvStorageUtils.getInvSnapshot(content)); + blockData.setBlockMenu(new BlockMenu(menuPreset, blockData.getLocation(), inv)); + + var content = blockData.getMenuContents(); + if (content != null) { + invSnapshots.put(blockData.getKey(), InvStorageUtils.getInvSnapshot(content)); + } } } - if (!universal && sfItem != null && sfItem.isTicking()) { + if (sfItem != null && sfItem.isTicking()) { Slimefun.getTickerTask().enableTicker(blockData.getLocation()); } - - // Universal data migration process - if (universal) { - migrateUniversalData(blockData); - } } finally { lock.unlock(key); } @@ -813,14 +816,6 @@ public void loadUniversalData(SlimefunUniversalData uniData) { uniData.setIsDataLoaded(true); - var sfItem = SlimefunItem.getById(uniData.getSfId()); - - if (sfItem != null && sfItem.isTicking()) { - if (!uniData.getLastPresent().getBlock().getType().isAir()) { - Slimefun.getTickerTask().enableTicker(uniData.getLastPresent(), uniData.getUUID()); - } - } - loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); var menuPreset = UniversalMenuPreset.getPreset(uniData.getSfId()); @@ -844,6 +839,14 @@ public void loadUniversalData(SlimefunUniversalData uniData) { invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); } } + + var sfItem = SlimefunItem.getById(uniData.getSfId()); + + if (sfItem != null && sfItem.isTicking()) { + if (!uniData.getLastPresent().getBlock().getType().isAir()) { + Slimefun.getTickerTask().enableTicker(uniData.getLastPresent(), uniData.getUUID()); + } + } } finally { lock.unlock(key); } @@ -1243,35 +1246,47 @@ private void clearBlockCacheAndTasks(SlimefunBlockData blockData) { /** * 迁移旧 Slimefun 机器数据至通用数据 - * - * @param blockData */ - private void migrateUniversalData(@Nonnull SlimefunBlockData blockData) { + private void migrateUniversalData( + @Nonnull Location l, + @Nonnull String sfId, + @Nonnull List kvData, + @Nonnull List invData) { try { - if (blockData == null || !blockData.isDataLoaded() || blockData.isPendingRemove()) { + if (l == null || sfId == null) { return; } - var universalData = createUniversalData(blockData.getLocation(), blockData.getSfId()); + var universalData = createUniversalData(l, sfId); - universalData.setLastPresent(new BlockPosition(blockData.getLocation())); + Slimefun.runSync( + () -> Slimefun.getBlockDataService() + .setUniversalDataUUID(l.getBlock(), String.valueOf(universalData.getUUID())), + 10L); - for (Map.Entry entry : blockData.getAllData().entrySet()) { - universalData.setData(entry.getKey(), entry.getValue()); - } + kvData.forEach(recordSet -> universalData.setData( + recordSet.get(FieldKey.DATA_KEY), DataUtils.blockDataDebase64(recordSet.get(FieldKey.DATA_VALUE)))); - final var oldMenu = blockData.getBlockMenu().getContents(); - final var newMenu = universalData.getUniversalMenu(); + var preset = UniversalMenuPreset.getPreset(sfId); + if (preset != null) { + final var inv = new ItemStack[54]; - for (int slot = 0; slot < oldMenu.length; slot++) { - if (newMenu.getPreset().getPresetSlots().contains(slot)) { - continue; - } + invData.forEach(record -> + inv[record.getInt(FieldKey.INVENTORY_SLOT)] = record.getItemStack(FieldKey.INVENTORY_ITEM)); - newMenu.addItem(slot, oldMenu[slot]); + universalData.setUniversalMenu(new UniversalMenu(preset, universalData.getUUID(), l, inv)); + + var content = universalData.getMenuContents(); + if (content != null) { + invSnapshots.put(universalData.getKey(), InvStorageUtils.getInvSnapshot(content)); + } } - removeBlockData(blockData.getLocation()); + removeBlockData(l); + + if (Slimefun.getRegistry().getTickerBlocks().contains(universalData.getSfId())) { + Slimefun.getTickerTask().enableTicker(universalData.getLastPresent(), universalData.getUUID()); + } } catch (Exception e) { Slimefun.logger().log(Level.WARNING, "迁移机器人数据时出现错误", e); } From ba3d64e268c4f311a7e5ef0a698f754d654cd945 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Fri, 25 Oct 2024 16:32:57 +0800 Subject: [PATCH 39/42] refactor: make universal data more flexible - Remove `last_present` field and use kv store to store it - Introduced `trait` for UniversalData to show their special ability - Spilt `SlimefunUniversalData` to `SlimefunUniversalData` and `SlimefunUniversalBlockData` - Refactor android menu --- .../slimefun4/api/menu}/UniversalMenu.java | 25 ++- .../api/menu}/UniversalMenuPreset.java | 6 +- .../storage/adapter/mysql/MysqlAdapter.java | 4 +- .../adapter/postgresql/PostgreSqlAdapter.java | 4 +- .../adapter/sqlcommon/SqlConstants.java | 2 +- .../storage/adapter/sqlcommon/SqlUtils.java | 4 +- .../storage/adapter/sqlite/SqliteAdapter.java | 4 +- .../slimefun4/storage/common/FieldKey.java | 2 +- .../controller/BlockDataController.java | 196 +++++++++++------- .../SlimefunUniversalBlockData.java | 45 ++++ .../controller/SlimefunUniversalData.java | 38 ++-- .../controller/attributes/UniversalBlock.java | 22 ++ .../attributes/UniversalDataTrait.java | 34 +++ .../migrator/BlockStorageMigrator.java | 2 +- .../storage/util/StorageCacheUtils.java | 19 +- .../slimefun4/api/ErrorReport.java | 4 +- .../core/attributes/UniversalDataSupport.java | 20 -- .../core/services/BlockDataService.java | 2 +- .../items/androids/AndroidAction.java | 2 +- .../items/androids/FarmerAndroid.java | 2 +- .../items/androids/FishermanAndroid.java | 2 +- .../items/androids/Instruction.java | 2 +- .../items/androids/MinerAndroid.java | 2 +- .../items/androids/ProgrammableAndroid.java | 133 +++++------- .../items/androids/WoodcutterAndroid.java | 2 +- .../listeners/BlockListener.java | 6 +- .../listeners/DebugFishListener.java | 2 +- .../SlimefunItemInteractListener.java | 8 +- .../implementation/tasks/TickerTask.java | 10 +- 29 files changed, 355 insertions(+), 249 deletions(-) rename src/main/java/{me/mrCookieSlime/Slimefun/api/inventory => city/norain/slimefun4/api/menu}/UniversalMenu.java (67%) rename src/main/java/{me/mrCookieSlime/Slimefun/api/inventory => city/norain/slimefun4/api/menu}/UniversalMenuPreset.java (89%) create mode 100644 src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java create mode 100644 src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalBlock.java create mode 100644 src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java delete mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java similarity index 67% rename from src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java rename to src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java index e469f7852e..c5f7491342 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenu.java +++ b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenu.java @@ -1,8 +1,10 @@ -package me.mrCookieSlime.Slimefun.api.inventory; +package city.norain.slimefun4.api.menu; import java.util.UUID; import javax.annotation.Nonnull; import lombok.Getter; +import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; +import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import org.bukkit.Location; import org.bukkit.inventory.ItemStack; @@ -14,7 +16,11 @@ public class UniversalMenu extends DirtyChestMenu { @Getter private final UUID uuid; - public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, @Nonnull Location lastPresent) { + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid) { + this(preset, uuid, (Location) null); + } + + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, Location lastPresent) { super(preset); this.uuid = uuid; @@ -23,10 +29,7 @@ public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, @N } public UniversalMenu( - @Nonnull UniversalMenuPreset preset, - @Nonnull UUID uuid, - @Nonnull Location lastPresent, - ItemStack[] contents) { + @Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, Location lastPresent, ItemStack[] contents) { super(preset); this.uuid = uuid; @@ -42,6 +45,10 @@ public UniversalMenu( this.getContents(); } + public UniversalMenu(@Nonnull UniversalMenuPreset preset, @Nonnull UUID uuid, ItemStack[] contents) { + this(preset, uuid, null, contents); + } + public void update(@Nonnull Location lastPresent) { ((UniversalMenuPreset) preset).clone(this, lastPresent); } @@ -50,10 +57,8 @@ public void update(@Nonnull Location lastPresent) { * This method drops the contents of this {@link BlockMenu} on the ground at the given * {@link Location}. * - * @param l - * Where to drop these items - * @param slots - * The slots of items that should be dropped + * @param l Where to drop these items + * @param slots The slots of items that should be dropped */ public void dropItems(Location l, int... slots) { for (int slot : slots) { diff --git a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java similarity index 89% rename from src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java rename to src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java index 3a845e5859..50fb73a937 100644 --- a/src/main/java/me/mrCookieSlime/Slimefun/api/inventory/UniversalMenuPreset.java +++ b/src/main/java/city/norain/slimefun4/api/menu/UniversalMenuPreset.java @@ -1,9 +1,11 @@ -package me.mrCookieSlime.Slimefun.api.inventory; +package city.norain.slimefun4.api.menu; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; +import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu; import org.bukkit.Location; import org.bukkit.block.Block; @@ -31,7 +33,7 @@ protected void clone(@Nonnull DirtyChestMenu menu) { return; } - clone(universalMenu, uniData.getLastPresent()); + clone(universalMenu, uniData.getLastPresent().toLocation()); } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java index c3aa958840..28f8bb655b 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/mysql/MysqlAdapter.java @@ -9,12 +9,12 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; -import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_TRAITS; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlCommonAdapter; @@ -345,7 +345,7 @@ private void createUniversalRecordTable() { + " CHAR(64) NOT NULL, " + FIELD_SLIMEFUN_ID + " CHAR(64) NOT NULL, " - + FIELD_LAST_PRESENT + + FIELD_UNIVERSAL_TRAITS + " CHAR(64) NOT NULL, " + "PRIMARY KEY (" + FIELD_UNIVERSAL_UUID diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java index 577e3a388d..8d4ab96c7a 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/postgresql/PostgreSqlAdapter.java @@ -9,12 +9,12 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; -import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_TRAITS; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlCommonAdapter; @@ -363,7 +363,7 @@ private void createUniversalRecordTable() { + " UUID NOT NULL, " + FIELD_SLIMEFUN_ID + " TEXT NOT NULL, " - + FIELD_LAST_PRESENT + + FIELD_UNIVERSAL_TRAITS + " TEXT NOT NULL, " + "PRIMARY KEY (" + FIELD_UNIVERSAL_UUID diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java index dc113a43b7..77af94134a 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlConstants.java @@ -35,5 +35,5 @@ public interface SqlConstants { String FIELD_UNIVERSAL_UUID = "universal_uuid"; - String FIELD_LAST_PRESENT = "last_present"; + String FIELD_UNIVERSAL_TRAITS = "universal_traits"; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java index fd7bb83e44..d9a9d189f9 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlcommon/SqlUtils.java @@ -9,12 +9,12 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; -import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_TRAITS; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_BACKPACK; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.TABLE_NAME_BACKPACK_INVENTORY; @@ -64,7 +64,7 @@ public class SqlUtils { fieldMap.put(FieldKey.DATA_KEY, FIELD_DATA_KEY); fieldMap.put(FieldKey.DATA_VALUE, FIELD_DATA_VALUE); fieldMap.put(FieldKey.UNIVERSAL_UUID, FIELD_UNIVERSAL_UUID); - fieldMap.put(FieldKey.LAST_PRESENT, FIELD_LAST_PRESENT); + fieldMap.put(FieldKey.UNIVERSAL_TRAITS, FIELD_UNIVERSAL_TRAITS); mapper = new FieldMapper<>(fieldMap); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java index ccefb9cf30..e11f5b1f52 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/adapter/sqlite/SqliteAdapter.java @@ -9,12 +9,12 @@ import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_DATA_VALUE; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_ITEM; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_INVENTORY_SLOT; -import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LAST_PRESENT; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_LOCATION; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_NAME; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_PLAYER_UUID; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_RESEARCH_KEY; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_SLIMEFUN_ID; +import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_TRAITS; import static com.xzavier0722.mc.plugin.slimefun4.storage.adapter.sqlcommon.SqlConstants.FIELD_UNIVERSAL_UUID; import city.norain.slimefun4.timings.entry.SQLEntry; @@ -344,7 +344,7 @@ private void createUniversalRecordTable() { + " CHAR(64) NOT NULL, " + FIELD_SLIMEFUN_ID + " CHAR(64) NOT NULL, " - + FIELD_LAST_PRESENT + + FIELD_UNIVERSAL_TRAITS + " CHAR(64) NOT NULL, " + "PRIMARY KEY (" + FIELD_UNIVERSAL_UUID diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java index a3e9e1065c..c7044b44e3 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/common/FieldKey.java @@ -27,7 +27,7 @@ public enum FieldKey { */ UNIVERSAL_UUID, - LAST_PRESENT; + UNIVERSAL_TRAITS; private final boolean isNumType; diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 0440f1defd..8e96f7cf29 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -1,5 +1,7 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; +import city.norain.slimefun4.api.menu.UniversalMenu; +import city.norain.slimefun4.api.menu.UniversalMenuPreset; import city.norain.slimefun4.utils.InventoryUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.adapter.IDataSourceAdapter; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; @@ -9,17 +11,18 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.common.RecordKey; import com.xzavier0722.mc.plugin.slimefun4.storage.common.RecordSet; import com.xzavier0722.mc.plugin.slimefun4.storage.common.ScopeKey; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalBlock; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalDataTrait; import com.xzavier0722.mc.plugin.slimefun4.storage.event.SlimefunChunkDataLoadEvent; import com.xzavier0722.mc.plugin.slimefun4.storage.task.DelayedSavingLooperTask; import com.xzavier0722.mc.plugin.slimefun4.storage.task.DelayedTask; import com.xzavier0722.mc.plugin.slimefun4.storage.util.DataUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.InvStorageUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; -import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.bakedlibs.dough.collections.Pair; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -35,8 +38,6 @@ import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenuPreset; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -133,7 +134,7 @@ private void initLoadData() { Slimefun.instance(), () -> { initLoading = true; - loadUniversalData(); + loadUniversalRecord(); initLoading = false; }, 1); @@ -230,8 +231,8 @@ public ASlimefunDataContainer createBlock(Location l, String sfId) { checkDestroy(); var sfItem = SlimefunItem.getById(sfId); - if (sfItem instanceof UniversalDataSupport) { - var re = createUniversalData(l, sfId); + if (sfItem instanceof UniversalBlock) { + var re = createUniversalBlockData(l, sfId); if (Slimefun.getRegistry().getTickerBlocks().contains(sfId)) { Slimefun.getTickerTask().enableTicker(l); } @@ -247,11 +248,11 @@ public ASlimefunDataContainer createBlock(Location l, String sfId) { @Nonnull @ParametersAreNonnullByDefault - public SlimefunUniversalData createUniversalData(Location l, String sfId) { + public SlimefunUniversalBlockData createUniversalBlockData(Location l, String sfId) { checkDestroy(); var uuid = UUID.randomUUID(); - var uniData = new SlimefunUniversalData(uuid, new BlockPosition(l), sfId); + var uniData = new SlimefunUniversalBlockData(uuid, sfId, l); uniData.setIsDataLoaded(true); @@ -259,10 +260,12 @@ public SlimefunUniversalData createUniversalData(Location l, String sfId) { var preset = UniversalMenuPreset.getPreset(sfId); if (preset != null) { - uniData.setUniversalMenu(new UniversalMenu(preset, uuid, l)); + uniData.setMenu(new UniversalMenu(preset, uuid, l)); } - Slimefun.getDatabaseManager().getBlockDataController().saveUniversalData(uuid, sfId, l); + Slimefun.getDatabaseManager() + .getBlockDataController() + .saveUniversalData(uuid, sfId, Set.of(UniversalDataTrait.BLOCK, UniversalDataTrait.INVENTORY)); return uniData; } @@ -289,13 +292,15 @@ void saveNewBlock(Location l, String sfId) { * @param uuid universal data uuid * @param sfId the item universal data represents */ - void saveUniversalData(UUID uuid, String sfId, Location l) { + void saveUniversalData(UUID uuid, String sfId, Set traits) { var key = new RecordKey(DataScope.UNIVERSAL_RECORD); var data = new RecordSet(); data.put(FieldKey.UNIVERSAL_UUID, uuid.toString()); data.put(FieldKey.SLIMEFUN_ID, sfId); - data.put(FieldKey.LAST_PRESENT, LocationUtils.getLocKey(l)); + data.put( + FieldKey.UNIVERSAL_TRAITS, + String.join(",", traits.stream().map(Enum::name).toList())); var scopeKey = new UUIDKey(DataScope.NONE, uuid); removeDelayedBlockDataUpdates(scopeKey); // Shouldn't have.. But for safe.. @@ -312,13 +317,14 @@ public void removeBlock(Location l) { var removed = getChunkDataCache(l.getChunk(), true).removeBlockData(l); if (removed == null) { - getUniversalDataFromCache(l).ifPresentOrElse(data -> removeUniversalData(l, data.getUUID()), () -> { - if (Bukkit.isPrimaryThread()) { - Slimefun.getBlockDataService() - .getUniversalDataUUID(l.getBlock()) - .ifPresent(uuid -> removeUniversalData(l, uuid)); - } - }); + getUniversalBlockDataFromCache(l) + .ifPresentOrElse(data -> removeUniversalBlockData(data.getUUID(), l), () -> { + if (Bukkit.isPrimaryThread()) { + Slimefun.getBlockDataService() + .getUniversalDataUUID(l.getBlock()) + .ifPresent(uuid -> removeUniversalBlockData(uuid, l)); + } + }); return; } @@ -356,7 +362,7 @@ public void removeBlockData(Location l) { } } - public void removeUniversalData(Location lastPresent, UUID uuid) { + public void removeUniversalBlockData(UUID uuid, Location lastPresent) { checkDestroy(); var toRemove = loadedUniversalData.get(uuid); @@ -369,19 +375,21 @@ public void removeUniversalData(Location lastPresent, UUID uuid) { return; } - toRemove.setPendingRemove(true); - removeUniversalBlockDirectly(uuid); + if (toRemove instanceof SlimefunUniversalBlockData ubd) { + toRemove.setPendingRemove(true); + removeUniversalBlockDirectly(uuid); - var menu = toRemove.getUniversalMenu(); - if (menu != null) { - InventoryUtil.closeInventory(menu.toInventory()); - } + var menu = ubd.getMenu(); + if (menu != null) { + menu.lock(); + } - if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { - Slimefun.getTickerTask().disableTicker(lastPresent); - } + if (Slimefun.getRegistry().getTickerBlocks().contains(toRemove.getSfId())) { + Slimefun.getTickerTask().disableTicker(lastPresent); + } - loadedUniversalData.remove(uuid); + loadedUniversalData.remove(uuid); + } } void removeBlockDirectly(Location l) { @@ -467,22 +475,30 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { * * @param uuid universal data uuid {@link UUID} */ - @Nullable public SlimefunUniversalData getUniversalData(@Nonnull UUID uuid) { + @Nullable public SlimefunUniversalBlockData getUniversalBlockData(@Nonnull UUID uuid) { checkDestroy(); var key = new RecordKey(DataScope.UNIVERSAL_RECORD); key.addCondition(FieldKey.UNIVERSAL_UUID, uuid.toString()); key.addField(FieldKey.SLIMEFUN_ID); - key.addField(FieldKey.LAST_PRESENT); var result = getData(key); - return result.isEmpty() - ? null - : new SlimefunUniversalData( - uuid, - new BlockPosition(LocationUtils.toLocation(result.get(0).get(FieldKey.LAST_PRESENT))), - result.get(0).get(FieldKey.SLIMEFUN_ID)); + if (result.isEmpty()) { + return null; + } + + var newData = new SlimefunUniversalBlockData(uuid, result.get(0).get(FieldKey.SLIMEFUN_ID)); + + Arrays.stream(result.get(0).get(FieldKey.UNIVERSAL_TRAITS).split(",")).forEach(tname -> { + for (UniversalDataTrait trait : UniversalDataTrait.getTraits()) { + if (trait.name().equals(tname)) { + newData.getTraits().add(trait); + } + } + }); + + return newData; } /** @@ -491,8 +507,8 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { * @param uuid universal data uuid {@link UUID} * @param callback operation when block data fetched {@link IAsyncReadCallback} */ - public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback callback) { - scheduleReadTask(() -> invokeCallback(callback, getUniversalData(uuid))); + public void getUniversalBlockData(@Nonnull UUID uuid, IAsyncReadCallback callback) { + scheduleReadTask(() -> invokeCallback(callback, getUniversalBlockData(uuid))); } /** @@ -500,12 +516,14 @@ public void getUniversalDataAsync(@Nonnull UUID uuid, IAsyncReadCallback getUniversalDataFromCache(@Nonnull Location l) { + public Optional getUniversalBlockDataFromCache(@Nonnull Location l) { checkDestroy(); return loadedUniversalData.values().stream() - .filter(uniData -> uniData.getLastPresent().equals(l)) + .filter(uniData -> uniData instanceof SlimefunUniversalBlockData ubd + && ubd.getLastPresent().toLocation().equals(l)) + .map(data -> (SlimefunUniversalBlockData) data) .findFirst(); } @@ -667,11 +687,11 @@ public void loadWorld(World world) { Level.INFO, "世界 {0} 数据加载完成, 耗时 {1}ms", new Object[] {worldName, (System.currentTimeMillis() - start)}); } - public void loadUniversalData() { + public void loadUniversalRecord() { var uniKey = new RecordKey(DataScope.UNIVERSAL_RECORD); uniKey.addField(FieldKey.UNIVERSAL_UUID); uniKey.addField(FieldKey.SLIMEFUN_ID); - uniKey.addField(FieldKey.LAST_PRESENT); + uniKey.addField(FieldKey.UNIVERSAL_TRAITS); getData(uniKey).forEach(data -> { var sfId = data.get(FieldKey.SLIMEFUN_ID); @@ -682,9 +702,22 @@ public void loadUniversalData() { } var uuid = data.getUUID(FieldKey.UNIVERSAL_UUID); - var location = LocationUtils.toLocation(data.get(FieldKey.LAST_PRESENT)); + var traitsData = data.get(FieldKey.UNIVERSAL_TRAITS); + var traits = new HashSet(); + + if (traitsData != null && !traitsData.isBlank()) { + for (String traitStr : traitsData.split(",")) { + try { + traits.add(UniversalDataTrait.valueOf(traitStr.toUpperCase())); + } catch (IllegalArgumentException ignored) {} + } + } + + var uniData = traits.contains(UniversalDataTrait.BLOCK) + ? new SlimefunUniversalBlockData(uuid, sfId) + : new SlimefunUniversalData(uuid, sfId); - var uniData = new SlimefunUniversalData(uuid, new BlockPosition(location), sfId); + traits.forEach(t -> uniData.getTraits().add(t)); scheduleReadTask(() -> loadUniversalData(uniData)); }); @@ -731,7 +764,7 @@ public void loadBlockData(SlimefunBlockData blockData) { } var sfItem = SlimefunItem.getById(blockData.getSfId()); - var universal = sfItem instanceof UniversalDataSupport; + var universal = sfItem instanceof UniversalBlock; var kvData = getData(key); @@ -818,33 +851,45 @@ public void loadUniversalData(SlimefunUniversalData uniData) { loadedUniversalData.putIfAbsent(uniData.getUUID(), uniData); - var menuPreset = UniversalMenuPreset.getPreset(uniData.getSfId()); - if (menuPreset != null) { - var menuKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); - menuKey.addCondition(FieldKey.UNIVERSAL_UUID, uniData.getKey()); - menuKey.addField(FieldKey.INVENTORY_SLOT); - menuKey.addField(FieldKey.INVENTORY_ITEM); + if (uniData.hasTrait(UniversalDataTrait.INVENTORY)) { + var menuPreset = UniversalMenuPreset.getPreset(uniData.getSfId()); + if (menuPreset != null) { + var menuKey = new RecordKey(DataScope.UNIVERSAL_INVENTORY); + menuKey.addCondition(FieldKey.UNIVERSAL_UUID, uniData.getKey()); + menuKey.addField(FieldKey.INVENTORY_SLOT); + menuKey.addField(FieldKey.INVENTORY_ITEM); + + var inv = new ItemStack[54]; - var inv = new ItemStack[54]; + getData(menuKey) + .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = + recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); - getData(menuKey) - .forEach(recordSet -> inv[recordSet.getInt(FieldKey.INVENTORY_SLOT)] = - recordSet.getItemStack(FieldKey.INVENTORY_ITEM)); + var location = uniData.hasTrait(UniversalDataTrait.BLOCK) + ? ((SlimefunUniversalBlockData) uniData) + .getLastPresent() + .toLocation() + : null; - uniData.setUniversalMenu( - new UniversalMenu(menuPreset, uniData.getUUID(), uniData.getLastPresent(), inv)); + uniData.setMenu(new UniversalMenu(menuPreset, uniData.getUUID(), location, inv)); - var content = uniData.getMenuContents(); - if (content != null) { - invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); + var content = uniData.getMenuContents(); + if (content != null) { + invSnapshots.put(uniData.getKey(), InvStorageUtils.getInvSnapshot(content)); + } } } - var sfItem = SlimefunItem.getById(uniData.getSfId()); + if (uniData.hasTrait(UniversalDataTrait.BLOCK)) { + var sfItem = SlimefunItem.getById(uniData.getSfId()); - if (sfItem != null && sfItem.isTicking()) { - if (!uniData.getLastPresent().getBlock().getType().isAir()) { - Slimefun.getTickerTask().enableTicker(uniData.getLastPresent(), uniData.getUUID()); + if (sfItem != null && sfItem.isTicking()) { + Slimefun.getTickerTask() + .enableTicker( + ((SlimefunUniversalBlockData) uniData) + .getLastPresent() + .toLocation(), + uniData.getUUID()); } } } finally { @@ -892,7 +937,7 @@ public void saveAllUniversalInventories() { if (data.isPendingRemove() || !data.isDataLoaded()) { return; } - var menu = data.getUniversalMenu(); + var menu = data.getMenu(); if (menu == null || !menu.isDirty()) { return; } @@ -973,7 +1018,7 @@ public void removeAllDataInWorldAsync(World world, Runnable onFinishedCallback) } public void saveUniversalInventory(@Nonnull SlimefunUniversalData universalData) { - var menu = universalData.getUniversalMenu(); + var menu = universalData.getMenu(); var universalID = universalData.getUUID(); var newInv = menu.getContents(); @@ -1257,11 +1302,11 @@ private void migrateUniversalData( return; } - var universalData = createUniversalData(l, sfId); + var universalData = createUniversalBlockData(l, sfId); Slimefun.runSync( () -> Slimefun.getBlockDataService() - .setUniversalDataUUID(l.getBlock(), String.valueOf(universalData.getUUID())), + .updateUniversalDataUUID(l.getBlock(), String.valueOf(universalData.getUUID())), 10L); kvData.forEach(recordSet -> universalData.setData( @@ -1274,7 +1319,7 @@ private void migrateUniversalData( invData.forEach(record -> inv[record.getInt(FieldKey.INVENTORY_SLOT)] = record.getItemStack(FieldKey.INVENTORY_ITEM)); - universalData.setUniversalMenu(new UniversalMenu(preset, universalData.getUUID(), l, inv)); + universalData.setMenu(new UniversalMenu(preset, universalData.getUUID(), l, inv)); var content = universalData.getMenuContents(); if (content != null) { @@ -1285,7 +1330,8 @@ private void migrateUniversalData( removeBlockData(l); if (Slimefun.getRegistry().getTickerBlocks().contains(universalData.getSfId())) { - Slimefun.getTickerTask().enableTicker(universalData.getLastPresent(), universalData.getUUID()); + Slimefun.getTickerTask() + .enableTicker(universalData.getLastPresent().toLocation(), universalData.getUUID()); } } catch (Exception e) { Slimefun.logger().log(Level.WARNING, "迁移机器人数据时出现错误", e); diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java new file mode 100644 index 0000000000..8c63037b04 --- /dev/null +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java @@ -0,0 +1,45 @@ +package com.xzavier0722.mc.plugin.slimefun4.storage.controller; + +import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; +import io.github.bakedlibs.dough.blocks.BlockPosition; +import java.util.UUID; +import org.bukkit.Location; + +public class SlimefunUniversalBlockData extends SlimefunUniversalData { + private volatile BlockPosition lastPresent; + + public SlimefunUniversalBlockData(UUID uuid, String sfId) { + super(uuid, sfId); + } + + public SlimefunUniversalBlockData(UUID uuid, String sfId, BlockPosition present) { + super(uuid, sfId); + + this.lastPresent = present; + } + + public SlimefunUniversalBlockData(UUID uuid, String sfId, Location present) { + this(uuid, sfId, new BlockPosition(present)); + } + + public void setLastPresent(BlockPosition lastPresent) { + setData("location", LocationUtils.locationToString(lastPresent.toLocation())); + this.lastPresent = lastPresent; + } + + public BlockPosition getLastPresent() { + if (lastPresent != null) { + return lastPresent; + } + + var data = getData("location"); + + if (data == null) { + throw new IllegalArgumentException("UniversalBlockData missing location data"); + } + + lastPresent = new BlockPosition(LocationUtils.toLocation(data)); + + return lastPresent; + } +} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index 52aad69ef4..cf8b284cd8 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -1,35 +1,30 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; -import io.github.bakedlibs.dough.blocks.BlockPosition; +import city.norain.slimefun4.api.menu.UniversalMenu; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalDataTrait; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import lombok.Getter; import lombok.Setter; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; -import org.bukkit.Location; import org.bukkit.inventory.ItemStack; -@Setter @Getter public class SlimefunUniversalData extends ASlimefunDataContainer { - private volatile UniversalMenu universalMenu; - - @Nullable private volatile BlockPosition lastPresent; + @Setter + private volatile UniversalMenu menu; + @Setter private volatile boolean pendingRemove = false; - @ParametersAreNonnullByDefault - SlimefunUniversalData(UUID uuid, BlockPosition location, String sfId) { - super(uuid.toString(), sfId); - this.lastPresent = location; - } + private final Set traits = new HashSet<>(); @ParametersAreNonnullByDefault - SlimefunUniversalData(UUID uuid, BlockPosition location, SlimefunUniversalData other) { - super(uuid.toString(), other, other.getSfId()); - this.lastPresent = location; + SlimefunUniversalData(UUID uuid, String sfId) { + super(uuid.toString(), sfId); } @ParametersAreNonnullByDefault @@ -47,12 +42,12 @@ public void removeData(String key) { } @Nullable public ItemStack[] getMenuContents() { - if (universalMenu == null) { + if (menu == null) { return null; } var re = new ItemStack[54]; - var presetSlots = universalMenu.getPreset().getPresetSlots(); - var inv = universalMenu.toInventory().getContents(); + var presetSlots = menu.getPreset().getPresetSlots(); + var inv = menu.toInventory().getContents(); for (var i = 0; i < inv.length; i++) { if (presetSlots.contains(i)) { continue; @@ -67,12 +62,13 @@ public UUID getUUID() { return UUID.fromString(getKey()); } - public Location getLastPresent() { - return this.lastPresent.toLocation(); + public boolean hasTrait(UniversalDataTrait trait) { + return traits.contains(trait); } @Override public String toString() { - return "SlimefunUniversalData [sfId=" + getSfId() + ", isPendingRemove=" + pendingRemove + "]"; + return "SlimefunUniversalData [uuid= " + getUUID() + ", sfId=" + getSfId() + ", isPendingRemove=" + + pendingRemove + "]"; } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalBlock.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalBlock.java new file mode 100644 index 0000000000..0717588fc4 --- /dev/null +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalBlock.java @@ -0,0 +1,22 @@ +package com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes; + +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; + +/** + * 这个属性用于声明 {@link SlimefunItem} 使用了 {@link SlimefunUniversalData} + *

+ * 当这个 {@link SlimefunItem} 作为机器时, 对应材质需要支持 + * 使用 PDC 存储容器 (用于识别 UUID). + * 否则无法将这个物品/机器绑定到一个通用数据上. + * + * 查看此处了解支持 PDC 的物品材质: + * Paper Doc + * + * @author NoRainCity + * + * @see SlimefunUniversalData + * @see SlimefunUniversalBlockData + */ +public interface UniversalBlock {} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java new file mode 100644 index 0000000000..149c2f1739 --- /dev/null +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java @@ -0,0 +1,34 @@ +package com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes; + +import city.norain.slimefun4.api.menu.UniversalMenu; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import lombok.Getter; + +/** + * 这个枚举类用于声明 {@link SlimefunUniversalData} 的特征. + * 一个通用数据可以有单个或多个特征. + *

+ * 对于一个通用数据, 它默认拥有作为 k-v 容器的特征. + * + * @see SlimefunUniversalData + * @see SlimefunUniversalBlockData + */ +@Getter +public enum UniversalDataTrait { + /** + * BLOCK 特征标明该通用数据属于 {@link SlimefunUniversalBlockData} + */ + BLOCK("location"), + + /** + * INVENTORY 特征标明该通用数据拥有一个 {@link UniversalMenu} + */ + INVENTORY(""); + + UniversalDataTrait(String reverseKey) {} + + public static UniversalDataTrait[] getTraits() { + return UniversalDataTrait.values(); + } +} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java index 03c7e1ac77..79f19083e5 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/migrator/BlockStorageMigrator.java @@ -152,7 +152,7 @@ private void migrateBlock(World world, String sfId, String locStr, String jsonSt if (sfData instanceof SlimefunBlockData blockData) { menu = blockData.getBlockMenu(); } else if (sfData instanceof SlimefunUniversalData uniData) { - menu = uniData.getUniversalMenu(); + menu = uniData.getMenu(); } if (menu != null) { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java index 57df8ef797..066f7974d8 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/util/StorageCacheUtils.java @@ -1,10 +1,12 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.util; +import city.norain.slimefun4.api.menu.UniversalMenu; import com.google.common.base.Preconditions; import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ADataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -16,7 +18,6 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Location; import org.bukkit.block.Block; @@ -125,8 +126,8 @@ public static void removeData(Location loc, String key) { } @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalBlock(UUID uuid) { - var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); + @Nullable public static SlimefunUniversalBlockData getUniversalBlock(UUID uuid) { + var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalBlockDataFromCache(uuid); if (uniData == null) { return null; @@ -141,7 +142,7 @@ public static void removeData(Location loc, String key) { } @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalBlock(UUID uuid, Location l) { + @Nullable public static SlimefunUniversalBlockData getUniversalBlock(UUID uuid, Location l) { var uniData = getUniversalBlock(uuid); if (uniData != null) { @@ -157,10 +158,10 @@ public static void removeData(Location loc, String key) { * You **must** call this method from sync! * * @param block {@link Block} - * @return {@link SlimefunUniversalData} + * @return {@link SlimefunUniversalBlockData} */ @ParametersAreNonnullByDefault - @Nullable public static SlimefunUniversalData getUniversalBlock(Block block) { + @Nullable public static SlimefunUniversalBlockData getUniversalBlock(Block block) { var uuid = Slimefun.getBlockDataService().getUniversalDataUUID(block); return uuid.map(id -> getUniversalBlock(id, block.getLocation())).orElse(null); @@ -182,12 +183,12 @@ public static void removeData(Location loc, String key) { return null; } - return uniData.getUniversalMenu(); + return uniData.getMenu(); } @ParametersAreNonnullByDefault @Nullable public static UniversalMenu getUniversalMenu(UUID uuid, Location l) { - var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid); + var uniData = Slimefun.getDatabaseManager().getBlockDataController().getUniversalBlockDataFromCache(uuid); if (uniData == null) { return null; @@ -200,7 +201,7 @@ public static void removeData(Location loc, String key) { uniData.setLastPresent(new BlockPosition(l)); - return uniData.getUniversalMenu(); + return uniData.getMenu(); } public static boolean isBlockPendingRemove(@Nonnull Block block) { diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java index a343d7a8dd..60bd92e010 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/api/ErrorReport.java @@ -115,10 +115,10 @@ public ErrorReport(T throwable, Location l, SlimefunItem item) { uuid -> { var universalData = Slimefun.getDatabaseManager() .getBlockDataController() - .getUniversalDataFromCache(uuid); + .getUniversalBlockDataFromCache(uuid); if (universalData != null) { stream.println(" 数据加载状态: " + universalData.isDataLoaded()); - stream.println(" 物品栏: " + (universalData.getUniversalMenu() != null)); + stream.println(" 物品栏: " + (universalData.getMenu() != null)); stream.println(" 数据: "); universalData .getAllData() diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java deleted file mode 100644 index 3489f74cb8..0000000000 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/attributes/UniversalDataSupport.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.thebusybiscuit.slimefun4.core.attributes; - -import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; -import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; - -/** - * This attribute represents {@link SlimefunItem} support store - * {@link SlimefunUniversalData} - * - * The {@link SlimefunItem} to be universal is encouraged be able to use PDC. - * Otherwise, it will lose its uuid to identify. - * - * Check here to find out what type of block can support this: - * Paper Doc - * - * @author NoRainCity - * - * @see SlimefunUniversalData - */ -public interface UniversalDataSupport {} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java index 6b4fbfedff..8aeda5a4bf 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/BlockDataService.java @@ -75,7 +75,7 @@ public void setBlockData(@Nonnull Block b, @Nonnull String value) { * @param uuid * The uuid linked to certain slimefun item */ - public void setUniversalDataUUID(@Nonnull Block b, @Nonnull String uuid) { + public void updateUniversalDataUUID(@Nonnull Block b, @Nonnull String uuid) { setBlockData(b, universalDataKey, uuid); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java index ff004a57ec..1a64173d95 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/AndroidAction.java @@ -1,6 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; +import city.norain.slimefun4.api.menu.UniversalMenu; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java index 0a403632d2..7289bed084 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FarmerAndroid.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.api.menu.UniversalMenu; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.protection.Interaction; import io.github.thebusybiscuit.slimefun4.api.events.AndroidFarmEvent; @@ -11,7 +12,6 @@ import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java index 4eae2ccab4..a40d77df38 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/FishermanAndroid.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.api.menu.UniversalMenu; import io.github.bakedlibs.dough.collections.RandomizedSet; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; @@ -7,7 +8,6 @@ import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect; import java.util.concurrent.ThreadLocalRandom; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java index da37c669e2..675f8a0a7b 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/Instruction.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.api.menu.UniversalMenu; import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import java.util.HashMap; @@ -8,7 +9,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.block.Block; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java index c25da9f0f7..c6f76dc91d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/MinerAndroid.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.api.menu.UniversalMenu; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.protection.Interaction; import io.github.thebusybiscuit.slimefun4.api.events.AndroidMineEvent; @@ -17,7 +18,6 @@ import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java index b6f5787253..8c0a1fbf00 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/ProgrammableAndroid.java @@ -1,6 +1,10 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.api.menu.UniversalMenu; +import city.norain.slimefun4.api.menu.UniversalMenuPreset; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalBlock; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.blocks.BlockPosition; @@ -17,7 +21,6 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem; -import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.core.attributes.rotations.NotDiagonallyRotatable; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; @@ -46,13 +49,10 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenuPreset; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.Tag; @@ -71,7 +71,7 @@ import org.bukkit.inventory.meta.ItemMeta; public class ProgrammableAndroid extends SlimefunItem - implements InventoryBlock, RecipeDisplayItem, NotDiagonallyRotatable, UniversalDataSupport { + implements InventoryBlock, RecipeDisplayItem, NotDiagonallyRotatable, UniversalBlock { private static final List POSSIBLE_ROTATIONS = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST); @@ -125,12 +125,9 @@ public boolean canOpen(Block b, Player p) { @Override public void newInstance(UniversalMenu menu, Block b) { - var uniData = StorageCacheUtils.getUniversalBlock(menu.getUuid(), b.getLocation()); + var uniData = StorageCacheUtils.getUniversalBlock(menu.getUuid()); - Objects.requireNonNull( - uniData, - "Unable to get android's universal data at " + LocationUtils.locationToString(b.getLocation()) - + "!"); + Objects.requireNonNull(uniData, "Unable to get android's universal data for " + menu.getUuid() + "!"); menu.replaceExistingItem( 15, new CustomItemStack(HeadTexture.SCRIPT_START.getAsItemStack(), "&a启动/继续运行")); @@ -155,7 +152,7 @@ public void newInstance(UniversalMenu menu, Block b) { menu.addMenuClickHandler(16, (p, slot, item, action) -> { uniData.setData("paused", "true"); Slimefun.getLocalization().sendMessage(p, "android.stopped", true); - openScriptEditor(p, b); + openScriptEditor(p, uniData); return false; }); @@ -218,15 +215,8 @@ private BlockBreakHandler onBreak() { @Override public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List drops) { Block b = e.getBlock(); - Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); - if (uuid.isEmpty()) { - throw new IllegalStateException( - "Missing universal id android @" + LocationUtils.locationToString(b.getLocation())); - } - - var uniData = - Slimefun.getDatabaseManager().getBlockDataController().getUniversalDataFromCache(uuid.get()); + var uniData = StorageCacheUtils.getUniversalBlock(b); if (uniData != null) { if (!e.getPlayer().hasPermission("slimefun.android.bypass") @@ -236,11 +226,14 @@ public void onPlayerBreak(BlockBreakEvent e, ItemStack item, List dro return; } - var menu = uniData.getUniversalMenu(); + var menu = uniData.getMenu(); if (menu != null) { menu.dropItems(b.getLocation(), 43); menu.dropItems(b.getLocation(), getOutputSlots()); } + } else { + throw new IllegalStateException( + "Missing universal id android @" + LocationUtils.locationToString(b.getLocation())); } } }; @@ -292,15 +285,10 @@ public boolean isSynchronized() { } @ParametersAreNonnullByDefault - public void openScript(Player p, Block b, String sourceCode) { + public void openScript(Player p, SlimefunUniversalBlockData uniData, String sourceCode) { ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); - Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); - - if (uuid.isEmpty()) { - throw new IllegalStateException("Android missing uuid"); - } menu.addItem( 0, @@ -310,7 +298,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(0, (pl, slot, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); + UniversalMenu inv = uniData.getMenu(); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -332,7 +320,7 @@ public void openScript(Player p, Block b, String sourceCode) { if (hasFreeSlot) { menu.addItem(i, new CustomItemStack(HeadTexture.SCRIPT_NEW.getAsItemStack(), "&7> 添加新命令")); menu.addMenuClickHandler(i, (pl, slot, item, action) -> { - editInstruction(pl, b, script, index); + editInstruction(pl, uniData, script, index); return false; }); } @@ -346,7 +334,7 @@ public void openScript(Player p, Block b, String sourceCode) { "", "&7\u21E8 &e左键 &7返回机器人的控制面板")); menu.addMenuClickHandler(slot, (pl, s, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); + UniversalMenu inv = uniData.getMenu(); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -390,14 +378,14 @@ public void openScript(Player p, Block b, String sourceCode) { } String code = duplicateInstruction(script, index); - setScript(b.getLocation(), code); - openScript(pl, b, code); + setScript(uniData, code); + openScript(pl, uniData, code); } else if (action.isRightClicked()) { String code = deleteInstruction(script, index); - setScript(b.getLocation(), code); - openScript(pl, b, code); + setScript(uniData, code); + openScript(pl, uniData, code); } else { - editInstruction(pl, b, script, index); + editInstruction(pl, uniData, script, index); } return false; @@ -463,7 +451,7 @@ private String deleteInstruction(String[] script, int index) { return builder.toString(); } - protected void openScriptDownloader(Player p, Block b, int page) { + protected void openScriptDownloader(Player p, SlimefunUniversalBlockData uniData, int page) { ChestMenu menu = new ChestMenu("机器人脚本"); menu.setEmptySlotsClickable(false); @@ -484,7 +472,7 @@ protected void openScriptDownloader(Player p, Block b, int page) { next = pages; } if (next != page) { - openScriptDownloader(pl, b, next); + openScriptDownloader(pl, uniData, next); } return false; }); @@ -494,7 +482,7 @@ protected void openScriptDownloader(Player p, Block b, int page) { new CustomItemStack( HeadTexture.SCRIPT_UP.getAsItemStack(), "&e上传脚本", "", "&6单击 &7将你正在用的脚本", "&7上传到服务器")); menu.addMenuClickHandler(48, (pl, slot, item, action) -> { - uploadScript(pl, b, page); + uploadScript(pl, uniData, page); return false; }); @@ -505,14 +493,14 @@ protected void openScriptDownloader(Player p, Block b, int page) { next = 1; } if (next != page) { - openScriptDownloader(pl, b, next); + openScriptDownloader(pl, uniData, next); } return false; }); menu.addItem(53, new CustomItemStack(HeadTexture.SCRIPT_LEFT.getAsItemStack(), "&6> 返回", "", "&7返回机器人控制面板")); menu.addMenuClickHandler(53, (pl, slot, item, action) -> { - openScriptEditor(pl, b); + openScriptEditor(pl, uniData); return false; }); @@ -533,14 +521,14 @@ protected void openScriptDownloader(Player p, Block b, int page) { Slimefun.getLocalization().sendMessage(player, "android.scripts.rating.own", true); } else if (script.canRate(player)) { script.rate(player, !action.isRightClicked()); - openScriptDownloader(player, b, page); + openScriptDownloader(player, uniData, page); } else { Slimefun.getLocalization().sendMessage(player, "android.scripts.rating.already", true); } } else if (!action.isRightClicked()) { script.download(); - setScript(b.getLocation(), script.getSourceCode()); - openScriptEditor(player, b); + setScript(uniData, script.getSourceCode()); + openScriptEditor(player, uniData); } } catch (Exception x) { Slimefun.logger() @@ -561,8 +549,8 @@ protected void openScriptDownloader(Player p, Block b, int page) { } @ParametersAreNonnullByDefault - private void uploadScript(Player p, Block b, int page) { - String code = getScript(b.getLocation()); + private void uploadScript(Player p, SlimefunUniversalBlockData uniData, int page) { + String code = getScript(uniData); int nextId = 1; for (Script script : Script.getUploadedScripts(getAndroidType())) { @@ -583,34 +571,23 @@ private void uploadScript(Player p, Block b, int page) { ChatInput.waitForPlayer(Slimefun.instance(), p, msg -> { Script.upload(p, getAndroidType(), id, msg, code); Slimefun.getLocalization().sendMessages(p, "android.scripts.uploaded"); - openScriptDownloader(p, b, page); + openScriptDownloader(p, uniData, page); }); } - public void openScriptEditor(Player p, Block b) { + public void openScriptEditor(Player p, SlimefunUniversalBlockData uniData) { ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); menu.setEmptySlotsClickable(false); - Optional uuid = Slimefun.getBlockDataService().getUniversalDataUUID(b); - - if (uuid.isEmpty()) { - throw new IllegalStateException("Android missing uuid"); - } - menu.addItem(1, new CustomItemStack(HeadTexture.SCRIPT_FORWARD.getAsItemStack(), "&2> 编辑脚本", "", "&a修改你现有的脚本")); menu.addMenuClickHandler(1, (pl, slot, item, action) -> { - String script = StorageCacheUtils.getData(b.getLocation(), "script"); - // Fixes #2937 - if (script != null) { - if (CommonPatterns.DASH.split(script).length <= MAX_SCRIPT_LENGTH) { - openScript(pl, b, getScript(b.getLocation())); - } else { - pl.closeInventory(); - Slimefun.getLocalization().sendMessage(pl, "android.scripts.too-long"); - } + String script = getScript(uniData); + if (CommonPatterns.DASH.split(script).length <= MAX_SCRIPT_LENGTH) { + openScript(pl, uniData, script); } else { pl.closeInventory(); + Slimefun.getLocalization().sendMessage(pl, "android.scripts.too-long"); } return false; }); @@ -620,7 +597,7 @@ public void openScriptEditor(Player p, Block b) { new CustomItemStack( HeadTexture.SCRIPT_NEW.getAsItemStack(), "&4> 创建新脚本", "", "&c删除你正在使用的脚本", "&c并创建一个全新的空白脚本")); menu.addMenuClickHandler(3, (pl, slot, item, action) -> { - openScript(pl, b, DEFAULT_SCRIPT); + openScript(pl, uniData, DEFAULT_SCRIPT); return false; }); @@ -633,13 +610,13 @@ public void openScriptEditor(Player p, Block b) { "&e从服务器中下载其他玩家上传的脚本", "&e可以即下即用, 或者修改之后再使用")); menu.addMenuClickHandler(5, (pl, slot, item, action) -> { - openScriptDownloader(pl, b, 1); + openScriptDownloader(pl, uniData, 1); return false; }); menu.addItem(8, new CustomItemStack(HeadTexture.SCRIPT_LEFT.getAsItemStack(), "&6> 返回", "", "&7返回机器人控制面板")); menu.addMenuClickHandler(8, (pl, slot, item, action) -> { - UniversalMenu inv = StorageCacheUtils.getUniversalMenu(uuid.get(), b.getLocation()); + UniversalMenu inv = uniData.getMenu(); // Fixes #2937 if (inv != null) { inv.open(pl); @@ -669,7 +646,7 @@ protected List getValidScriptInstructions() { return list; } - protected void editInstruction(Player p, Block b, String[] script, int index) { + protected void editInstruction(Player p, SlimefunUniversalBlockData uniData, String[] script, int index) { ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + Slimefun.getLocalization().getMessage(p, "android.scripts.editor")); ChestMenuUtils.drawBackground(menu, 0, 1, 2, 3, 4, 5, 6, 7, 8); @@ -680,8 +657,8 @@ protected void editInstruction(Player p, Block b, String[] script, int index) { new CustomItemStack(HeadTexture.SCRIPT_PAUSE.getAsItemStack(), "&f什么也不做"), (pl, slot, item, action) -> { String code = deleteInstruction(script, index); - setScript(b.getLocation(), code); - openScript(p, b, code); + setScript(uniData, code); + openScript(p, uniData, code); return false; }); @@ -695,8 +672,8 @@ protected void editInstruction(Player p, Block b, String[] script, int index) { .getMessage(p, "android.scripts.instructions." + instruction.name())), (pl, slot, item, action) -> { String code = addInstruction(script, index, instruction); - setScript(b.getLocation(), code); - openScript(p, b, code); + setScript(uniData, code); + openScript(p, uniData, code); return false; }); @@ -707,14 +684,14 @@ protected void editInstruction(Player p, Block b, String[] script, int index) { } @Nonnull - public String getScript(@Nonnull Location l) { - Validate.notNull(l, "Location for android not specified"); - String script = StorageCacheUtils.getData(l, "script"); + public String getScript(@Nonnull SlimefunUniversalBlockData ubd) { + Validate.notNull(ubd, "SlimefunUniversalBlockData for android not specified"); + String script = ubd.getData("script"); return script != null ? script : DEFAULT_SCRIPT; } - public void setScript(@Nonnull Location l, @Nonnull String script) { - Validate.notNull(l, "Location for android not specified"); + public void setScript(@Nonnull SlimefunUniversalBlockData ubd, @Nonnull String script) { + Validate.notNull(ubd, "SlimefunUniversalBlockData for android not specified"); Validate.notNull(script, "No script given"); Validate.isTrue(script.startsWith(Instruction.START.name() + '-'), "A script must begin with a 'START' token."); Validate.isTrue(script.endsWith('-' + Instruction.REPEAT.name()), "A script must end with a 'REPEAT' token."); @@ -722,7 +699,7 @@ public void setScript(@Nonnull Location l, @Nonnull String script) { CommonPatterns.DASH.split(script).length <= MAX_SCRIPT_LENGTH, "Scripts may not have more than " + MAX_SCRIPT_LENGTH + " segments"); - StorageCacheUtils.setData(l, "script", script); + ubd.setData("script", script); } private void registerDefaultFuelTypes() { @@ -810,7 +787,7 @@ protected void tick(Block b, SlimefunUniversalData data) { } if ("false".equals(data.getData("paused"))) { - UniversalMenu menu = data.getUniversalMenu(); + UniversalMenu menu = data.getMenu(); String fuelData = data.getData("fuel"); float fuel = fuelData == null ? 0 : Float.parseFloat(fuelData); @@ -1060,7 +1037,7 @@ protected void move(Block from, BlockFace face, Block to) { })); Slimefun.getBlockDataService() - .setUniversalDataUUID(to, uniData.getUUID().toString()); + .updateUniversalDataUUID(to, uniData.getUUID().toString()); Slimefun.runSync(() -> { PlayerSkin skin = PlayerSkin.fromBase64(texture); @@ -1073,7 +1050,7 @@ protected void move(Block from, BlockFace face, Block to) { from.setType(Material.AIR); uniData.setLastPresent(new BlockPosition(to.getLocation())); - uniData.getUniversalMenu().update(to.getLocation()); + uniData.getMenu().update(to.getLocation()); Slimefun.getTickerTask().enableTicker(to.getLocation(), uniData.getUUID()); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java index 8329d35f4d..ec37eb41e4 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/androids/WoodcutterAndroid.java @@ -1,5 +1,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids; +import city.norain.slimefun4.api.menu.UniversalMenu; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.blocks.Vein; import io.github.bakedlibs.dough.protection.Interaction; @@ -14,7 +15,6 @@ import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; -import me.mrCookieSlime.Slimefun.api.inventory.UniversalMenu; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java index 2aa955229e..2a2588f7c7 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/BlockListener.java @@ -2,7 +2,7 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; -import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.protection.Interaction; import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion; @@ -158,9 +158,9 @@ public void onBlockPlace(BlockPlaceEvent e) { .getBlockDataController() .createBlock(block.getLocation(), sfItem.getId()); - if (data instanceof SlimefunUniversalData) { + if (data instanceof SlimefunUniversalBlockData) { if (Slimefun.getBlockDataService().isTileEntity(block.getType())) { - Slimefun.getBlockDataService().setUniversalDataUUID(block, data.getKey()); + Slimefun.getBlockDataService().updateUniversalDataUUID(block, data.getKey()); } else { throw new IllegalStateException( "You must use pdc support material for this Slimefun item!"); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java index 1bcedc901b..7de1d5077f 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/DebugFishListener.java @@ -199,7 +199,7 @@ private void sendInfo(Player p, Block b, ASlimefunDataContainer data) { } if ((data instanceof SlimefunBlockData bd && bd.getBlockMenu() != null) - || (data instanceof SlimefunUniversalData ud && ud.getUniversalMenu() != null)) { + || (data instanceof SlimefunUniversalData ud && ud.getMenu() != null)) { p.sendMessage(ChatColors.color("&dInventory: " + greenCheckmark)); } else { p.sendMessage(ChatColors.color("&dInventory: " + redCross)); diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java index 4b225a331a..c71b300770 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunItemInteractListener.java @@ -3,10 +3,10 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.callback.IAsyncReadCallback; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalBlock; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler; import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; @@ -143,7 +143,7 @@ private void openInventory(Player p, SlimefunItem item, Block clickedBlock, Play if (!p.isSneaking() || event.getItem().getType() == Material.AIR) { event.getInteractEvent().setCancelled(true); - if (item instanceof UniversalDataSupport) { + if (item instanceof UniversalBlock) { var uniData = StorageCacheUtils.getUniversalBlock(clickedBlock); if (uniData == null) { @@ -151,7 +151,7 @@ private void openInventory(Player p, SlimefunItem item, Block clickedBlock, Play } if (uniData.isDataLoaded()) { - openMenu(uniData.getUniversalMenu(), clickedBlock, p); + openMenu(uniData.getMenu(), clickedBlock, p); } else { Slimefun.getDatabaseManager() .getBlockDataController() @@ -167,7 +167,7 @@ public void onResult(SlimefunUniversalData result) { return; } - openMenu(result.getUniversalMenu(), clickedBlock, p); + openMenu(result.getMenu(), clickedBlock, p); } }); } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index af6d1eb91d..a9a596d10e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -3,12 +3,12 @@ import com.xzavier0722.mc.plugin.slimefun4.storage.controller.ASlimefunDataContainer; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunBlockData; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.SlimefunUniversalData; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalBlock; import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils; import io.github.bakedlibs.dough.blocks.BlockPosition; import io.github.bakedlibs.dough.blocks.ChunkPosition; import io.github.thebusybiscuit.slimefun4.api.ErrorReport; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.core.attributes.UniversalDataSupport; import io.github.thebusybiscuit.slimefun4.core.ticker.TickLocation; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.Collections; @@ -22,6 +22,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import lombok.Setter; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; import org.apache.commons.lang.Validate; import org.bukkit.Chunk; @@ -55,6 +56,7 @@ public class TickerTask implements Runnable { private boolean halted = false; private boolean running = false; + @Setter private volatile boolean paused = false; /** @@ -336,7 +338,7 @@ public Set getLocations(@Nonnull Chunk chunk) { /** * 返回一个给定区块下的 只读 的 {@link Map} - * 代表每个 {@link ChunkPosition} 中有 {@link UniversalDataSupport} 属性的物品 + * 代表每个 {@link ChunkPosition} 中有 {@link UniversalBlock} 属性的物品 * Tick 的 {@link Location 位置}集合. * * 其中包含的 {@link Location} 可以是已加载或卸载的 {@link Chunk} @@ -434,8 +436,4 @@ public void disableTicker(@Nonnull UUID uuid) { tickingLocations.values().forEach(loc -> loc.removeIf(tk -> uuid.equals(tk.getUuid()))); } } - - public void setPaused(boolean isPaused) { - paused = isPaused; - } } From 286871be220c1db3b672d5ef796b5161a8971d41 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Fri, 25 Oct 2024 16:50:56 +0800 Subject: [PATCH 40/42] feat: add reserved key check --- .../norain/slimefun4/utils/ClassUtil.java | 16 +++++ .../city/norain/slimefun4/utils/PDCUtil.java | 67 ------------------- .../slimefun4/utils/pdctype/UUIDType.java | 40 ----------- .../controller/BlockDataController.java | 5 +- .../controller/SlimefunUniversalData.java | 10 +++ .../attributes/UniversalDataTrait.java | 16 ++++- 6 files changed, 42 insertions(+), 112 deletions(-) create mode 100644 src/main/java/city/norain/slimefun4/utils/ClassUtil.java delete mode 100644 src/main/java/city/norain/slimefun4/utils/PDCUtil.java delete mode 100644 src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java diff --git a/src/main/java/city/norain/slimefun4/utils/ClassUtil.java b/src/main/java/city/norain/slimefun4/utils/ClassUtil.java new file mode 100644 index 0000000000..ea25c7cd37 --- /dev/null +++ b/src/main/java/city/norain/slimefun4/utils/ClassUtil.java @@ -0,0 +1,16 @@ +package city.norain.slimefun4.utils; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class ClassUtil { + public String getCallerClass() { + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + + if (stackTrace.length > 3) { + return stackTrace[3].getClassName(); + } else { + return null; + } + } +} diff --git a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java b/src/main/java/city/norain/slimefun4/utils/PDCUtil.java deleted file mode 100644 index cb06f59646..0000000000 --- a/src/main/java/city/norain/slimefun4/utils/PDCUtil.java +++ /dev/null @@ -1,67 +0,0 @@ -package city.norain.slimefun4.utils; - -import city.norain.slimefun4.utils.pdctype.UUIDType; -import com.google.common.base.Preconditions; -import io.papermc.lib.PaperLib; -import java.util.UUID; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.bukkit.NamespacedKey; -import org.bukkit.block.Block; -import org.bukkit.block.TileState; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; - -public class PDCUtil { - public static final PersistentDataType UUID_TYPE = new UUIDType(); - - private PDCUtil() throws IllegalAccessException { - throw new IllegalAccessException("Utility Class"); - } - - public static void setValue( - @Nonnull Block block, - @Nonnull PersistentDataType type, - @Nonnull NamespacedKey key, - @Nonnull Z value) { - var state = (TileState) PaperLib.getBlockState(block, false); - var container = state.getPersistentDataContainer(); - - setValue(container, type, key, value); - } - - public static void setValue( - @Nonnull PersistentDataContainer container, - @Nonnull PersistentDataType type, - @Nonnull NamespacedKey key, - @Nonnull Z value) { - Preconditions.checkArgument(container != null, "Container cannot be null!"); - Preconditions.checkArgument(type != null, "PDC type cannot be null!"); - Preconditions.checkArgument(key != null, "PDC key cannot be null!"); - - container.set(key, type, value); - } - - @Nullable public static Z getValue( - @Nonnull Block block, @Nonnull PersistentDataType type, @Nonnull NamespacedKey key) { - var state = (TileState) PaperLib.getBlockState(block, false); - var container = state.getPersistentDataContainer(); - - return getValue(container, type, key); - } - - @Nullable public static Z getValue( - @Nonnull PersistentDataContainer container, - @Nonnull PersistentDataType type, - @Nonnull NamespacedKey key) { - Preconditions.checkArgument(container != null, "Container cannot be null!"); - Preconditions.checkArgument(type != null, "PDC type cannot be null!"); - Preconditions.checkArgument(key != null, "PDC key cannot be null!"); - - if (container.has(key, type)) { - return container.get(key, type); - } else { - return null; - } - } -} diff --git a/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java b/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java deleted file mode 100644 index 3c719e8f9c..0000000000 --- a/src/main/java/city/norain/slimefun4/utils/pdctype/UUIDType.java +++ /dev/null @@ -1,40 +0,0 @@ -package city.norain.slimefun4.utils.pdctype; - -import java.nio.ByteBuffer; -import java.util.UUID; -import javax.annotation.Nonnull; -import org.bukkit.persistence.PersistentDataAdapterContext; -import org.bukkit.persistence.PersistentDataType; - -public class UUIDType implements PersistentDataType { - - @Nonnull - @Override - public Class getPrimitiveType() { - return byte[].class; - } - - @Nonnull - @Override - public Class getComplexType() { - return UUID.class; - } - - @Nonnull - @Override - public byte[] toPrimitive(final UUID complex, @Nonnull final PersistentDataAdapterContext context) { - var bb = ByteBuffer.wrap(new byte[16]); - bb.putLong(complex.getMostSignificantBits()); - bb.putLong(complex.getLeastSignificantBits()); - return bb.array(); - } - - @Nonnull - @Override - public UUID fromPrimitive(@Nonnull final byte[] primitive, @Nonnull final PersistentDataAdapterContext context) { - var bb = ByteBuffer.wrap(primitive); - var mostBits = bb.getLong(); - var leastBits = bb.getLong(); - return new UUID(mostBits, leastBits); - } -} diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 8e96f7cf29..6449dd232d 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -491,7 +491,7 @@ public SlimefunBlockData getBlockDataFromCache(Location l) { var newData = new SlimefunUniversalBlockData(uuid, result.get(0).get(FieldKey.SLIMEFUN_ID)); Arrays.stream(result.get(0).get(FieldKey.UNIVERSAL_TRAITS).split(",")).forEach(tname -> { - for (UniversalDataTrait trait : UniversalDataTrait.getTraits()) { + for (UniversalDataTrait trait : UniversalDataTrait.values()) { if (trait.name().equals(tname)) { newData.getTraits().add(trait); } @@ -709,7 +709,8 @@ public void loadUniversalRecord() { for (String traitStr : traitsData.split(",")) { try { traits.add(UniversalDataTrait.valueOf(traitStr.toUpperCase())); - } catch (IllegalArgumentException ignored) {} + } catch (IllegalArgumentException ignored) { + } } } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index cf8b284cd8..fac6edaf42 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -1,6 +1,7 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; import city.norain.slimefun4.api.menu.UniversalMenu; +import city.norain.slimefun4.utils.ClassUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalDataTrait; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.HashSet; @@ -30,6 +31,15 @@ public class SlimefunUniversalData extends ASlimefunDataContainer { @ParametersAreNonnullByDefault public void setData(String key, String val) { checkData(); + + if (UniversalDataTrait.isReservedKey(key)) { + var caller = ClassUtil.getCallerClass(); + + if (!caller.startsWith("com.xzavier0722.mc.plugin.slimefun4.storage.controller")) { + throw new RuntimeException("You cannot set data for reserved key!"); + } + } + setCacheInternal(key, val, true); Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, key); } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java index 149c2f1739..4d402a4118 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/attributes/UniversalDataTrait.java @@ -26,9 +26,19 @@ public enum UniversalDataTrait { */ INVENTORY(""); - UniversalDataTrait(String reverseKey) {} + private final String reservedKey; - public static UniversalDataTrait[] getTraits() { - return UniversalDataTrait.values(); + UniversalDataTrait(String reservedKey) { + this.reservedKey = reservedKey; + } + + public static boolean isReservedKey(String key) { + for (UniversalDataTrait trait : UniversalDataTrait.values()) { + if (trait.getReservedKey().equals(key)) { + return true; + } + } + + return false; } } From 165cfdc8835b93e219c7c570d9601e32c0f35794 Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 9 Nov 2024 15:22:47 +0800 Subject: [PATCH 41/42] fix(unidata): use proper way to reserved key --- .../controller/SlimefunUniversalBlockData.java | 3 ++- .../controller/SlimefunUniversalData.java | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java index 8c63037b04..c1b4355dd2 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalBlockData.java @@ -1,5 +1,6 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; +import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalDataTrait; import com.xzavier0722.mc.plugin.slimefun4.storage.util.LocationUtils; import io.github.bakedlibs.dough.blocks.BlockPosition; import java.util.UUID; @@ -23,7 +24,7 @@ public SlimefunUniversalBlockData(UUID uuid, String sfId, Location present) { } public void setLastPresent(BlockPosition lastPresent) { - setData("location", LocationUtils.locationToString(lastPresent.toLocation())); + setTraitData(UniversalDataTrait.BLOCK, LocationUtils.locationToString(lastPresent.toLocation())); this.lastPresent = lastPresent; } diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index fac6edaf42..8f5d38c900 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -7,6 +7,7 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.logging.Level; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import lombok.Getter; @@ -33,17 +34,24 @@ public void setData(String key, String val) { checkData(); if (UniversalDataTrait.isReservedKey(key)) { - var caller = ClassUtil.getCallerClass(); - - if (!caller.startsWith("com.xzavier0722.mc.plugin.slimefun4.storage.controller")) { - throw new RuntimeException("You cannot set data for reserved key!"); - } + Slimefun.logger().log(Level.WARNING, "警告: 有附属正在尝试修改受保护的方块数据, 已取消更改"); + return; } setCacheInternal(key, val, true); Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, key); } + @ParametersAreNonnullByDefault + protected void setTraitData(UniversalDataTrait trait, String val) { + checkData(); + + if (!trait.getReservedKey().isBlank()) { + setCacheInternal(trait.getReservedKey(), val, true); + Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, trait.getReservedKey()); + } + } + @ParametersAreNonnullByDefault public void removeData(String key) { if (removeCacheInternal(key) != null || !isDataLoaded()) { From 385137de7c5eb227d5b78756e6b883d1194ab72f Mon Sep 17 00:00:00 2001 From: StarWishsama Date: Sat, 9 Nov 2024 15:53:14 +0800 Subject: [PATCH 42/42] fix: uni block ticker not be enabled --- .../slimefun4/storage/controller/BlockDataController.java | 2 +- .../slimefun4/storage/controller/SlimefunUniversalData.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java index 6449dd232d..e097ae654e 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/BlockDataController.java @@ -234,7 +234,7 @@ public ASlimefunDataContainer createBlock(Location l, String sfId) { if (sfItem instanceof UniversalBlock) { var re = createUniversalBlockData(l, sfId); if (Slimefun.getRegistry().getTickerBlocks().contains(sfId)) { - Slimefun.getTickerTask().enableTicker(l); + Slimefun.getTickerTask().enableTicker(l, re.getUUID()); } return re; } else { diff --git a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java index 8f5d38c900..baf6d59829 100644 --- a/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java +++ b/src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java @@ -1,7 +1,6 @@ package com.xzavier0722.mc.plugin.slimefun4.storage.controller; import city.norain.slimefun4.api.menu.UniversalMenu; -import city.norain.slimefun4.utils.ClassUtil; import com.xzavier0722.mc.plugin.slimefun4.storage.controller.attributes.UniversalDataTrait; import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import java.util.HashSet; @@ -48,7 +47,9 @@ protected void setTraitData(UniversalDataTrait trait, String val) { if (!trait.getReservedKey().isBlank()) { setCacheInternal(trait.getReservedKey(), val, true); - Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, trait.getReservedKey()); + Slimefun.getDatabaseManager() + .getBlockDataController() + .scheduleDelayedUniversalDataUpdate(this, trait.getReservedKey()); } }