mirror of
https://github.com/AXOLOTsh/PluginUtils.git
synced 2026-09-21 03:46:23 +03:00
feature: add itemlore module
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package org.axolotsh.pluginutils.modules.itemlore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.axolotsh.pluginutils.modules.itemlore.entities.LoreEntry;
|
||||
import org.axolotsh.pluginutils.modules.itemlore.entities.LoreEntryType;
|
||||
import org.axolotsh.pluginutils.persistent_data_container.PersistentMap;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
@Getter
|
||||
@Accessors(chain = true, fluent = true)
|
||||
@AllArgsConstructor
|
||||
public class ItemLoreFactory {
|
||||
private final Configuration configuration;
|
||||
|
||||
@Getter
|
||||
@Accessors(chain = true, fluent = true)
|
||||
@Builder(toBuilder = true)
|
||||
public static class Configuration {
|
||||
@NonNull
|
||||
private String namespace;
|
||||
|
||||
@Builder.Default
|
||||
private String loreEntriesKey = "lore_entries";
|
||||
|
||||
public NamespacedKey loreEntries() {
|
||||
return new NamespacedKey(namespace, loreEntriesKey);
|
||||
};
|
||||
|
||||
public static Configuration fromPlugin(JavaPlugin plugin) {
|
||||
return builder()
|
||||
.namespace(plugin.namespace())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
public ItemLoreFactory(JavaPlugin plugin) {
|
||||
this(Configuration.fromPlugin(plugin));
|
||||
}
|
||||
|
||||
public ItemLoreService service(ItemStack item) {
|
||||
Map<Key, List<Component>> lore = new LinkedHashMap<>();
|
||||
var loreMap = loreEntries(item).get();
|
||||
var itemLore = item.lore();
|
||||
if (itemLore == null)
|
||||
itemLore = List.of();
|
||||
|
||||
var usedIndices = new boolean[itemLore.size()];
|
||||
|
||||
for (var entry : loreMap.entrySet()) {
|
||||
var info = entry.getValue();
|
||||
lore.put(entry.getKey(), info.get(itemLore));
|
||||
|
||||
var start = Math.min(info.position(), itemLore.size());
|
||||
var end = Math.min(info.endPosition(), itemLore.size());
|
||||
for (var i = start; i < end; i++)
|
||||
usedIndices[i] = true;
|
||||
}
|
||||
|
||||
List<Component> unmappedLines = new ArrayList<>();
|
||||
for (int i = 0; i < itemLore.size(); i++)
|
||||
if (!usedIndices[i])
|
||||
unmappedLines.add(itemLore.get(i));
|
||||
|
||||
if (!unmappedLines.isEmpty())
|
||||
lore.put(ItemLoreService.UNKNOWN_LORE_KEY, unmappedLines);
|
||||
|
||||
return new ItemLoreService(this, lore, item);
|
||||
}
|
||||
|
||||
PersistentMap<Key, LoreEntry> loreEntries(ItemStack item) {
|
||||
return new PersistentMap<Key, LoreEntry>(
|
||||
configuration.loreEntries(), LoreEntryType.INSTANCE, item,
|
||||
(entry) -> Map.entry(entry.id(), entry), LinkedHashMap::new);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.axolotsh.pluginutils.modules.itemlore;
|
||||
|
||||
import org.axolotsh.pluginutils.dependency_injection.PluginModule;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
public class ItemLoreModule extends PluginModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
protected ItemLoreFactory provideItemLoreFactory(JavaPlugin plugin) {
|
||||
return new ItemLoreFactory(plugin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.axolotsh.pluginutils.modules.itemlore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.axolotsh.pluginutils.modules.itemlore.entities.LoreEntry;
|
||||
import org.axolotsh.pluginutils.wrappers.MapWrapper;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ItemLoreService extends MapWrapper<Key, List<Component>> implements AutoCloseable {
|
||||
public static final Key UNKNOWN_LORE_KEY = Key.key("unknown_lore");
|
||||
|
||||
private final ItemLoreFactory factory;
|
||||
private final ItemStack item;
|
||||
|
||||
ItemLoreService(ItemLoreFactory factory, Map<Key, List<Component>> innerMap, ItemStack item) {
|
||||
super(innerMap);
|
||||
this.factory = factory;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
List<Component> lore = new ArrayList<>();
|
||||
Map<Key, LoreEntry> loreMap = new LinkedHashMap<>();
|
||||
|
||||
var position = 0;
|
||||
for (Map.Entry<Key, List<Component>> entry : innerMap.entrySet()) {
|
||||
var key = entry.getKey();
|
||||
var value = entry.getValue();
|
||||
|
||||
var size = value.size();
|
||||
if (!key.equals(UNKNOWN_LORE_KEY)) {
|
||||
var loreEntry = new LoreEntry(key, position, size);
|
||||
loreMap.put(key, loreEntry);
|
||||
}
|
||||
|
||||
lore.addAll(value);
|
||||
|
||||
position += size;
|
||||
}
|
||||
|
||||
factory.loreEntries(item).set(loreMap);
|
||||
item.lore(lore);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.axolotsh.pluginutils.modules.itemlore.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
@Getter
|
||||
@Accessors(chain = true, fluent = true)
|
||||
@Builder(toBuilder = true)
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor
|
||||
public class LoreEntry {
|
||||
@NonNull
|
||||
private Key id;
|
||||
|
||||
private int position;
|
||||
private int length;
|
||||
|
||||
public int endPosition() {
|
||||
return position + length;
|
||||
}
|
||||
|
||||
public List<Component> get(List<Component> lore) {
|
||||
Objects.requireNonNull(lore);
|
||||
|
||||
var toIndex = Math.min(endPosition(), lore.size());
|
||||
var fromIndex = Math.min(position, toIndex);
|
||||
|
||||
return new ArrayList<>(lore.subList(fromIndex, toIndex));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.axolotsh.pluginutils.modules.itemlore.entities;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
|
||||
public class LoreEntryType implements PersistentDataType<byte[], LoreEntry> {
|
||||
public static final LoreEntryType INSTANCE = new LoreEntryType();
|
||||
|
||||
private LoreEntryType() {
|
||||
};
|
||||
|
||||
@Override
|
||||
public @NotNull Class<byte[]> getPrimitiveType() {
|
||||
return byte[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Class<LoreEntry> getComplexType() {
|
||||
return LoreEntry.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte @NotNull [] toPrimitive(@NotNull LoreEntry complex, @NotNull PersistentDataAdapterContext context) {
|
||||
var baos = new ByteArrayOutputStream();
|
||||
try (var dos = new DataOutputStream(baos)) {
|
||||
dos.writeInt(complex.position());
|
||||
dos.writeInt(complex.length());
|
||||
|
||||
var id = complex.id();
|
||||
dos.writeUTF(id.asMinimalString());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull LoreEntry fromPrimitive(byte @NotNull [] primitive, @NotNull PersistentDataAdapterContext context) {
|
||||
var bais = new ByteArrayInputStream(primitive);
|
||||
try (var dis = new DataInputStream(bais)) {
|
||||
var position = dis.readInt();
|
||||
var length = dis.readInt();
|
||||
|
||||
var minimalString = dis.readUTF();
|
||||
var key = Key.key(minimalString);
|
||||
return new LoreEntry(key, position, length);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user