From 9ab9d7f11b834cd8c61767c9c53a353ecd0134c3 Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 30 Nov 2024 07:59:31 -0800
Subject: [PATCH 01/10] Citizen's hook WIP
---
pom.xml | 21 ++-
.../world/bentobox/bentobox/BentoBox.java | 4 +
.../blueprints/BlueprintClipboard.java | 42 +++--
.../bentobox/blueprints/BlueprintPaster.java | 28 ++-
.../dataobjects/BlueprintEntity.java | 38 ++++
.../bentobox/bentobox/hooks/CitizensHook.java | 165 ++++++++++++++++++
.../bentobox/util/DefaultPasteUtil.java | 17 +-
7 files changed, 299 insertions(+), 16 deletions(-)
create mode 100644 src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
diff --git a/pom.xml b/pom.xml
index 90bf01ed9..ed5c97230 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
-LOCAL
- 3.0.1
+ 3.1.0
bentobox-world
https://sonarcloud.io
${project.basedir}/lib
@@ -192,6 +192,11 @@
clojars
https://repo.clojars.org/
+
+
+ citizens-repo
+ https://maven.citizensnpcs.co/repo
+
@@ -387,6 +392,20 @@
1.1.13
compile
+
+
+ net.citizensnpcs
+ citizens-main
+ 2.0.35-SNAPSHOT
+ jar
+ provided
+
+
+ *
+ *
+
+
+
diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java
index daa0b91dd..ae4f06a60 100644
--- a/src/main/java/world/bentobox/bentobox/BentoBox.java
+++ b/src/main/java/world/bentobox/bentobox/BentoBox.java
@@ -24,6 +24,7 @@
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.commands.BentoBoxCommand;
import world.bentobox.bentobox.database.DatabaseSetup;
+import world.bentobox.bentobox.hooks.CitizensHook;
import world.bentobox.bentobox.hooks.ItemsAdderHook;
import world.bentobox.bentobox.hooks.MultipaperHook;
import world.bentobox.bentobox.hooks.MultiverseCoreHook;
@@ -192,6 +193,9 @@ private void completeSetup(long loadTime) {
hooksManager.registerHook(new VaultHook());
+ // Citizens
+ hooksManager.registerHook(new CitizensHook());
+
// MythicMobs
hooksManager.registerHook(new MythicMobsHook());
diff --git a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java
index d189f2df0..315ef66e8 100644
--- a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java
+++ b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java
@@ -2,7 +2,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -23,8 +22,8 @@
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.ChestedHorse;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.Horse;
-import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Villager;
@@ -44,6 +43,7 @@
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
+import world.bentobox.bentobox.hooks.CitizensHook;
import world.bentobox.bentobox.hooks.MythicMobsHook;
/**
@@ -70,20 +70,21 @@ public class BlueprintClipboard {
private final Map bpBlocks = new LinkedHashMap<>();
private final BentoBox plugin = BentoBox.getInstance();
private Optional mmh;
+ private Optional ch;
/**
* Create a clipboard for blueprint
* @param blueprint - the blueprint to load into the clipboard
*/
public BlueprintClipboard(@NonNull Blueprint blueprint) {
+ this();
this.blueprint = blueprint;
- // MythicMobs
- mmh = plugin.getHooks().getHook("MythicMobs").filter(MythicMobsHook.class::isInstance)
- .map(MythicMobsHook.class::cast);
}
public BlueprintClipboard() {
- // MythicMobs
+ // Citizens Hook
+ ch = plugin.getHooks().getHook("Citizens").filter(CitizensHook.class::isInstance).map(CitizensHook.class::cast);
+ // MythicMobs Hook
mmh = plugin.getHooks().getHook("MythicMobs").filter(MythicMobsHook.class::isInstance)
.map(MythicMobsHook.class::cast);
}
@@ -136,13 +137,20 @@ public boolean copy(User user, boolean copyAir, boolean copyBiome) {
private void copyAsync(World world, User user, List vectorsToCopy, int speed, boolean copyAir, boolean copyBiome) {
copying = false;
+ // Citizens
+ if (ch.isPresent()) {
+ // Add all the citizens for the area in one go. This is pretty fast.
+ bpEntities.putAll(ch.get().getCitizensInArea(world, vectorsToCopy, origin));
+ }
+
+ // Repeating copy task
copyTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
if (copying) {
return;
}
copying = true;
vectorsToCopy.stream().skip(index).limit(speed).forEach(v -> {
- List ents = world.getLivingEntities().stream()
+ List ents = world.getEntities().stream()
.filter(Objects::nonNull)
.filter(e -> !(e instanceof Player))
.filter(e -> new Vector(Math.rint(e.getLocation().getX()),
@@ -153,6 +161,7 @@ private void copyAsync(World world, User user, List vectorsToCopy, int s
count++;
}
});
+
index += speed;
int percent = (int)(index * 100 / (double)vectorsToCopy.size());
if (percent != lastPercentage && percent % 10 == 0) {
@@ -189,9 +198,9 @@ protected List getVectors(BoundingBox b) {
return r;
}
- private boolean copyBlock(Location l, boolean copyAir, boolean copyBiome, Collection entities) {
+ private boolean copyBlock(Location l, boolean copyAir, boolean copyBiome, List ents) {
Block block = l.getBlock();
- if (!copyAir && block.getType().equals(Material.AIR) && entities.isEmpty()) {
+ if (!copyAir && block.getType().equals(Material.AIR) && ents.isEmpty()) {
return false;
}
// Create position
@@ -202,14 +211,14 @@ private boolean copyBlock(Location l, boolean copyAir, boolean copyBiome, Collec
Vector pos = new Vector(x, y, z);
// Set entities
- List bpEnts = setEntities(entities);
+ List bpEnts = setEntities(ents);
// Store
if (!bpEnts.isEmpty()) {
bpEntities.put(pos, bpEnts);
}
// Return if this is just air block
- if (!copyAir && block.getType().equals(Material.AIR) && !entities.isEmpty()) {
+ if (!copyAir && block.getType().equals(Material.AIR) && !ents.isEmpty()) {
return true;
}
@@ -291,9 +300,15 @@ private BlueprintCreatureSpawner getSpawner(CreatureSpawner spawner) {
return cs;
}
- private List setEntities(Collection entities) {
+ /**
+ * Deals with any entities that are in this block. Technically, this could be more than one, but is usually one.
+ * @param ents collection of entities
+ * @return Serialized list of entities
+ */
+ private List setEntities(List ents) {
List bpEnts = new ArrayList<>();
- for (LivingEntity entity: entities) {
+ for (Entity entity : ents) {
+ BentoBox.getInstance().logDebug("Etity = " + entity);
BlueprintEntity bpe = new BlueprintEntity();
bpe.setType(entity.getType());
@@ -329,6 +344,7 @@ private List setEntities(Collection entities) {
bpe.setStyle(horse.getStyle());
}
+ // Mythic mob check
mmh.filter(mm -> mm.isMythicMob(entity)).map(mm -> mm.getMythicMob(entity))
.ifPresent(bpe::setMythicMobsRecord);
diff --git a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintPaster.java b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintPaster.java
index d62f8807d..8ba1cb498 100644
--- a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintPaster.java
+++ b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintPaster.java
@@ -124,12 +124,38 @@ public BlueprintPaster(@NonNull BentoBox plugin, @NonNull Blueprint bp, World wo
location.setY(y);
}
- private record Bits(Map blocks,
+ /**
+ * A record of all the "bits" of the blueprint that need to be pasted
+ * Consists of blocks, attached blocks, entities, iterators for the blocks and a speed
+ */
+ private record Bits(
+ /**
+ * Basic blocks to the pasted (not attached blocks)
+ */
+ Map blocks,
+ /**
+ * Attached blocks
+ */
Map attached,
+ /**
+ * Entities to be pasted
+ */
Map> entities,
+ /**
+ * Basic block pasting iterator
+ */
Iterator> it,
+ /**
+ * Attached block pasting iterator
+ */
Iterator> it2,
+ /**
+ * Entity pasting iterator
+ */
Iterator>> it3,
+ /**
+ * Paste speed
+ */
int pasteSpeed) {}
/**
diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java
index 4c4eb1de1..3c1e1959a 100644
--- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java
+++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java
@@ -24,6 +24,11 @@
*/
public class BlueprintEntity {
+ // Citizens storage
+ @Expose
+ private String citizen;
+
+ // MythicMobs storage
public record MythicMobRecord(String type, String displayName, double level, float power, String stance) {
}
@@ -303,5 +308,38 @@ public void setMythicMobsRecord(MythicMobRecord mmr) {
this.MMStance = mmr.stance();
this.MMpower = mmr.power();
}
+
+ /**
+ * @return the citizen
+ */
+ public String getCitizen() {
+ return citizen;
+ }
+
+ /**
+ * @param citizen the citizen to set
+ */
+ public void setCitizen(String citizen) {
+ this.citizen = citizen;
+ }
+
+ @Override
+ public String toString() {
+ return "BlueprintEntity [" + (citizen != null ? "citizen=" + citizen + ", " : "")
+ + (MMtype != null ? "MMtype=" + MMtype + ", " : "")
+ + (MMLevel != null ? "MMLevel=" + MMLevel + ", " : "")
+ + (MMStance != null ? "MMStance=" + MMStance + ", " : "")
+ + (MMpower != null ? "MMpower=" + MMpower + ", " : "") + (color != null ? "color=" + color + ", " : "")
+ + (type != null ? "type=" + type + ", " : "")
+ + (customName != null ? "customName=" + customName + ", " : "")
+ + (tamed != null ? "tamed=" + tamed + ", " : "") + (chest != null ? "chest=" + chest + ", " : "")
+ + (adult != null ? "adult=" + adult + ", " : "")
+ + (domestication != null ? "domestication=" + domestication + ", " : "")
+ + (inventory != null ? "inventory=" + inventory + ", " : "")
+ + (style != null ? "style=" + style + ", " : "") + (level != null ? "level=" + level + ", " : "")
+ + (profession != null ? "profession=" + profession + ", " : "")
+ + (experience != null ? "experience=" + experience + ", " : "")
+ + (villagerType != null ? "villagerType=" + villagerType : "") + "]";
+ }
}
diff --git a/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java b/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
new file mode 100644
index 000000000..ba64af478
--- /dev/null
+++ b/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
@@ -0,0 +1,165 @@
+package world.bentobox.bentobox.hooks;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.EntityType;
+import org.bukkit.util.Vector;
+import org.eclipse.jdt.annotation.Nullable;
+
+import net.citizensnpcs.api.CitizensAPI;
+import net.citizensnpcs.api.npc.NPC;
+import net.citizensnpcs.api.npc.NPCRegistry;
+import net.citizensnpcs.api.util.MemoryDataKey;
+import world.bentobox.bentobox.BentoBox;
+import world.bentobox.bentobox.api.hooks.Hook;
+import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
+
+/**
+ * Provides copy and pasting of Citizens in blueprints
+ *
+ * @author tastybento
+ * @since 3.1.0
+ */
+public class CitizensHook extends Hook {
+
+ MemoryDataKey dataKeyTest = new MemoryDataKey();
+
+ public CitizensHook() {
+ super("Citizens", Material.PLAYER_HEAD);
+ }
+
+ public String serializeNPC(NPC npc) {
+ if (npc == null) {
+ throw new IllegalArgumentException("NPC cannot be null.");
+ }
+ MemoryDataKey dataKey = new MemoryDataKey();
+ npc.save(dataKey); // Save NPC data into the MemoryDataKey
+ // Convert MemoryDataKey to a YAML string
+ YamlConfiguration yaml = new YamlConfiguration();
+ for (Entry en : dataKey.getValuesDeep().entrySet()) {
+ BentoBox.getInstance().logDebug("Serial key = " + en.getKey() + " = " + en.getValue());
+ yaml.set(en.getKey(), en.getValue());
+ }
+ dataKeyTest = dataKey;
+ return yaml.saveToString();
+ }
+
+ /**
+ * Get a map of serialized Citizens that are in a set of locations
+ * @param world world where this occurs
+ * @param vectorsToCopy list of locations in that world as vectors
+ * @param origin
+ * @return map
+ */
+ public Map> getCitizensInArea(World world, List vectorsToCopy,
+ @Nullable Vector origin) {
+ Map> bpEntities = new HashMap<>();
+ for (NPC npc : CitizensAPI.getNPCRegistry()) {
+ if (npc.isSpawned()) {
+ Location npcLocation = npc.getEntity().getLocation();
+ Vector spot = new Vector(npcLocation.getBlockX(), npcLocation.getBlockY(), npcLocation.getBlockZ());
+ if (npcLocation.getWorld().equals(world) && vectorsToCopy.contains(spot)) {
+ BlueprintEntity cit = new BlueprintEntity();
+ cit.setType(npc.getEntity().getType()); // Must be set to be pasted
+ cit.setCitizen(serializeNPC(npc));
+ // Retrieve or create the list, then add the entity
+ List entities = bpEntities.getOrDefault(spot, new ArrayList<>());
+ entities.add(cit);
+ // Create position
+ Vector origin2 = origin == null ? new Vector(0, 0, 0) : origin;
+ int x = spot.getBlockX() - origin2.getBlockX();
+ int y = spot.getBlockY() - origin2.getBlockY();
+ int z = spot.getBlockZ() - origin2.getBlockZ();
+ Vector pos = new Vector(x, y, z);
+ // Store
+ bpEntities.put(pos, entities); // Update the map
+ }
+ }
+ }
+ return bpEntities;
+ }
+
+ /**
+ * Spawn a Citizen
+ * @param serializedData serialized data
+ * @param location location
+ * @return true if spawn is successful
+ */
+ public boolean spawnCitizen(EntityType type, String serializedData, Location location) {
+ BentoBox.getInstance().logDebug("spawn Citizen at " + location + " with this data " + serializedData);
+ if (serializedData == null || location == null) {
+ throw new IllegalArgumentException("Serialized data and location cannot be null.");
+ }
+
+ // Load the serialized data into a YamlConfiguration
+ YamlConfiguration yaml = YamlConfiguration.loadConfiguration(new StringReader(serializedData));
+
+ // Create a new MemoryDataKey from the loaded data
+ MemoryDataKey dataKey = new MemoryDataKey();
+ for (String key : yaml.getKeys(true)) {
+ BentoBox.getInstance().logDebug("data key " + key + " = " + yaml.get(key));
+ if (key.equalsIgnoreCase("metadata") || key.equalsIgnoreCase("traits")
+ || key.equalsIgnoreCase("traits.owner") || key.equalsIgnoreCase("traits.location")
+ || key.equalsIgnoreCase("navigator")) {
+ continue;
+ }
+ dataKey.setRaw(key, yaml.get(key));
+ }
+
+ // Get the NPC details from the serialized data
+ String name = dataKey.getString("name");
+ //String type = dataKey.getString("traits.type");
+
+ BentoBox.getInstance().logDebug("Entity type = " + type + " name = " + name);
+ if (type == null) {
+ // No luck
+ return false;
+ }
+ // Create a new NPC and load the data
+ BentoBox.getInstance().logDebug("Create a new NPC and load the data");
+ NPCRegistry registry = CitizensAPI.getNPCRegistry();
+ try {
+ NPC npc = registry.createNPC(type, name);
+
+ npc.load(dataKey); // Load the serialized data into the NPC
+ for (Entry en : dataKey.getValuesDeep().entrySet()) {
+ BentoBox.getInstance().logDebug("loaded key " + en.getKey() + " = " + en.getValue());
+ }
+ boolean r = npc.spawn(location); // Spawn the NPC at the specified location
+ BentoBox.getInstance().logDebug("Spawn = " + r);
+ if (!r) {
+ npc.load(dataKeyTest);
+ BentoBox.getInstance().logDebug(npc.spawn(location)); // Spawn the NPC at the specified location
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+
+ @Override
+ public boolean hook() {
+ boolean hooked = this.isPluginAvailable();
+ if (!hooked) {
+ BentoBox.getInstance().logError("Could not hook into Citizens");
+ }
+ return hooked; // The hook process shouldn't fail
+ }
+
+ @Override
+ public String getFailureCause() {
+ return null; // The hook process shouldn't fail
+ }
+}
diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java
index 76fb68be9..c22ba05fe 100644
--- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java
+++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java
@@ -33,6 +33,7 @@
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
import world.bentobox.bentobox.database.objects.Island;
+import world.bentobox.bentobox.hooks.CitizensHook;
import world.bentobox.bentobox.hooks.MythicMobsHook;
import world.bentobox.bentobox.nms.PasteHandler;
@@ -169,8 +170,11 @@ public static void setSpawner(CreatureSpawner spawner, BlueprintCreatureSpawner
* @param island - island
* @param location - location
* @param list - blueprint entities
+ * @return future boolean - true if Bukkit entity spawned, false another plugin entity spawned
*/
public static CompletableFuture setEntity(Island island, Location location, List list) {
+ BentoBox.getInstance().logDebug("List of entities to paste at " + location);
+ list.forEach(bpe -> BentoBox.getInstance().logDebug(bpe));
World world = location.getWorld();
assert world != null;
return Util.getChunkAtAsync(location).thenRun(() -> list.stream().filter(k -> k.getType() != null)
@@ -182,9 +186,20 @@ public static CompletableFuture setEntity(Island island, Location location
* @param k the blueprint entity definition
* @param location location
* @param island island
- * @return true if Bukkit entity spawned, false if MythicMob entity spawned
+ * @return true if Bukkit entity spawned, false another plugin entity spawned
*/
static boolean spawnBlueprintEntity(BlueprintEntity k, Location location, Island island) {
+ BentoBox.getInstance().logDebug("pasting entity " + k.getType() + " at " + location);
+ // Citizens entity
+ if (k.getCitizen() != null && plugin.getHooks().getHook("Citizens").filter(mmh -> mmh instanceof CitizensHook)
+ .map(mmh -> ((CitizensHook) mmh).spawnCitizen(k.getType(), k.getCitizen(), location)).orElse(false)) {
+ BentoBox.getInstance().logDebug("Citizen spawning done");
+ // Citizen has spawned.
+ return false;
+ } else {
+ BentoBox.getInstance().logDebug("Citizen spawning failed");
+ }
+ // Mythic Mobs entity
if (k.getMythicMobsRecord() != null && plugin.getHooks().getHook("MythicMobs")
.filter(mmh -> mmh instanceof MythicMobsHook)
.map(mmh -> ((MythicMobsHook) mmh).spawnMythicMob(k.getMythicMobsRecord(), location))
From c8dc6188b966477a5ec4dab1aab39c156e56ac8c Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 30 Nov 2024 08:27:52 -0800
Subject: [PATCH 02/10] Updated some package-info javadocs
---
.../bentobox/api/addons/package-info.java | 20 +++++++++++++------
.../bentobox/api/commands/package-info.java | 14 +++++++++----
.../api/configuration/package-info.java | 4 +++-
.../bentobox/api/events/package-info.java | 13 +++++++++---
.../bentobox/bentobox/api/package-info.java | 10 ++++++++++
.../world/bentobox/bentobox/package-info.java | 14 +++++++++++++
.../bentobox/bentobox/util/package-info.java | 8 +++++++-
7 files changed, 68 insertions(+), 15 deletions(-)
create mode 100644 src/main/java/world/bentobox/bentobox/api/package-info.java
create mode 100644 src/main/java/world/bentobox/bentobox/package-info.java
diff --git a/src/main/java/world/bentobox/bentobox/api/addons/package-info.java b/src/main/java/world/bentobox/bentobox/api/addons/package-info.java
index 4d239fd0d..abf00000b 100644
--- a/src/main/java/world/bentobox/bentobox/api/addons/package-info.java
+++ b/src/main/java/world/bentobox/bentobox/api/addons/package-info.java
@@ -1,12 +1,20 @@
/**
- * This package covers all addon-specific API
- *
- * The Addon class and the associated Pladdon are like Bukkit plugins
- * but contain extra API specific for BentoBox games.
- *
+ * This package contains classes and interfaces related to BentoBox addons.
+ *
+ * Addons are modular extensions that enhance BentoBox functionality. Game-specific
+ * addons (e.g., BSkyBlock, AcidIsland) as well as generic addons (e.g., Challenges, Warps)
+ * are supported by this system. Developers can create custom addons to introduce
+ * new features or gamemodes.
+ *
+ * Since BentoBox was created, server tech has changed and code remapping is done and that
+ * is usually only applied when a Plugin is loaded, so developers should use Pladdons
+ * which are a wrapper for Addons in a Plugin.
+ *
+ * Key components:
+ * - AddonLoader: Manages the lifecycle of addons.
+ * - AddonConfig: Handles addon-specific configurations.
*
* @since 1.0
* @author tastybento
- *
*/
package world.bentobox.bentobox.api.addons;
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/api/commands/package-info.java b/src/main/java/world/bentobox/bentobox/api/commands/package-info.java
index 7c4212842..2c2306515 100644
--- a/src/main/java/world/bentobox/bentobox/api/commands/package-info.java
+++ b/src/main/java/world/bentobox/bentobox/api/commands/package-info.java
@@ -1,7 +1,9 @@
/**
- * API for BentoBox commands
- */
-/**
+ * This package contains classes and handlers for BentoBox commands.
+ *
+ * Commands allow players and administrators to interact with BentoBox, including
+ * managing islands, settings, and other in-game features. This package ensures
+ * smooth integration and execution of commands within the plugin.
*
* The workhorse class is the abstract class CompositeCommand. It provides all the functionality for
* a command including automatic help, sub-commands, convenience methods, etc. See examples of how to use
@@ -13,6 +15,10 @@
* their own custom help if required, but most of the time it is not.
*
* @author tastybento
- *
+ *
+ * Key features:
+ * - Command registration and parsing.
+ * - Support for custom addon-specific commands.
+ * - Error handling and permission validation.
*/
package world.bentobox.bentobox.api.commands;
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/api/configuration/package-info.java b/src/main/java/world/bentobox/bentobox/api/configuration/package-info.java
index 75ae81960..2beff6941 100644
--- a/src/main/java/world/bentobox/bentobox/api/configuration/package-info.java
+++ b/src/main/java/world/bentobox/bentobox/api/configuration/package-info.java
@@ -1,4 +1,6 @@
/**
- * Contains API related to configurations.
+ * Provides classes and interfaces for managing configuration settings within the BentoBox API.
+ * This package enables the definition, access, and manipulation of configuration options,
+ * facilitating the customization and extension of BentoBox's functionality.
*/
package world.bentobox.bentobox.api.configuration;
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/api/events/package-info.java b/src/main/java/world/bentobox/bentobox/api/events/package-info.java
index 326a59c8c..8709a133b 100644
--- a/src/main/java/world/bentobox/bentobox/api/events/package-info.java
+++ b/src/main/java/world/bentobox/bentobox/api/events/package-info.java
@@ -1,7 +1,14 @@
/**
- * API for all the events that BentoBox generates
- */
-/**
+ * This package defines events used within the BentoBox framework.
+ *
+ * Events are triggered during key gameplay actions, such as island creation,
+ * deletion, or player interactions. Developers can use these events to customize
+ * behaviors or respond to actions in their addons.
+ *
+ * Key features:
+ * - Custom event classes (e.g., IslandCreateEvent, PlayerJoinEvent).
+ * - Integration with Bukkit's event system.
+ *
* @author tastybento
*
*/
diff --git a/src/main/java/world/bentobox/bentobox/api/package-info.java b/src/main/java/world/bentobox/bentobox/api/package-info.java
new file mode 100644
index 000000000..19f31387b
--- /dev/null
+++ b/src/main/java/world/bentobox/bentobox/api/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * This package provides the core API for interacting with the BentoBox framework.
+ *
+ * It enables developers to integrate their custom plugins or addons with BentoBox,
+ * offering simplified access to common functionalities like:
+ * - Island management (creation, deletion, permissions).
+ * - Player interactions within island-based games.
+ * - Events and hooks for extending core behavior.
+ */
+package world.bentobox.bentobox.api;
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/package-info.java b/src/main/java/world/bentobox/bentobox/package-info.java
new file mode 100644
index 000000000..128bc2f0f
--- /dev/null
+++ b/src/main/java/world/bentobox/bentobox/package-info.java
@@ -0,0 +1,14 @@
+/**
+ * The core package for the BentoBox plugin.
+ *
+ * This package provides the foundational framework for island-based games like SkyBlock,
+ * AcidIsland, and others. It manages core plugin features such as the addon system,
+ * configuration, and APIs used by developers to create custom addons or extend
+ * the functionality of BentoBox.
+ *
+ * Key features:
+ * - A modular addon system to mix and match features and game modes.
+ * - Comprehensive APIs for island protection, GUIs, team management, and more.
+ * - Cross-compatibility with various game modes.
+ */
+package world.bentobox.bentobox;
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/util/package-info.java b/src/main/java/world/bentobox/bentobox/util/package-info.java
index 3b6d6e5c3..787a062db 100644
--- a/src/main/java/world/bentobox/bentobox/util/package-info.java
+++ b/src/main/java/world/bentobox/bentobox/util/package-info.java
@@ -5,7 +5,13 @@
* Look here before you write your own utility function. If it isn't here, but would be useful
* the submit a PR so others can avoid duplicating code!
*
- *
+ *
+ * This package provides utility classes and helpers for common tasks within BentoBox.
+ *
+ * These utilities simplify repetitive tasks like file handling, configuration management,
+ * and mathematical calculations. They are used throughout the framework and can be
+ * leveraged by addon developers.
+ *
* @author various
*
*/
From ff33cfe113fac266f05c0e3cd6110e0e35b7160c Mon Sep 17 00:00:00 2001
From: tastybento
Date: Wed, 4 Dec 2024 19:04:16 -0800
Subject: [PATCH 03/10] WIP
---
.../bentobox/bentobox/hooks/CitizensHook.java | 146 ++++++++++++------
1 file changed, 98 insertions(+), 48 deletions(-)
diff --git a/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java b/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
index ba64af478..e7d295f4e 100644
--- a/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
+++ b/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
@@ -1,17 +1,18 @@
package world.bentobox.bentobox.hooks;
-import java.io.StringReader;
-import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.UUID;
-import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.MemorySection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.EntityType;
import org.bukkit.util.Vector;
@@ -20,6 +21,7 @@
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.npc.NPCRegistry;
+import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.MemoryDataKey;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.hooks.Hook;
@@ -33,25 +35,99 @@
*/
public class CitizensHook extends Hook {
- MemoryDataKey dataKeyTest = new MemoryDataKey();
-
public CitizensHook() {
super("Citizens", Material.PLAYER_HEAD);
}
+ public static DataKey toDataKey(String serializedData) {
+ DataKey dataKey = new MemoryDataKey();
+ YamlConfiguration y = new YamlConfiguration();
+ try {
+ y.loadFromString(serializedData);
+ } catch (InvalidConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ insertIntoDataKey(dataKey, "", y);
+ return dataKey;
+ }
+
+ private static void insertIntoDataKey(DataKey dataKey, String parentPath, ConfigurationSection config2) {
+ // Manually set the keys and see where it breaks
+ dataKey.setString("name", "bentest");
+ dataKey.setString("uuid", UUID.randomUUID().toString());
+ dataKey.setString("traits.type", "PLAYER");
+ dataKey.setDouble("traits.location.bodyYaw", -111.14996);
+ dataKey.setDouble("traits.location.x", 0.0);
+ dataKey.setDouble("traits.location.y", 0.0);
+ dataKey.setDouble("traits.location.z", 0.0);
+ dataKey.setDouble("traits.location.yaw", -111.15);
+ dataKey.setDouble("traits.location.pitch", 42.0);
+ dataKey.setBoolean("spawned", true);
+ dataKey.setString("traitnames", "type,location,spawned");
+ dataKey.setString("metadata.cached-skin-uuid", "f4579458-a42d-431c-bbec-f7183536f633");
+ dataKey.setString("skintrait.signature",
+ "QBxcn0hclFKgSvGXjivL5W6F43uPuUFQgrvumsIPZEpdzR+LKXgl+OCfdoFCvjF303mDcpvMPcAJ9XEcbA/JLbeGkcfUupw326vjsz422lABA8Uys8yR/3lKD+KXfmvtpqiuOphMLvE21vVZQb0uP9g+1XgFO6puttcB3vGmenIM7jFE3uyQ8ma44VMqv/QBz8RHCw6jn+HsuIqS/VBQ/wv+/FVDOYd+qq4nbIXEyfZK/mvRlq4+AaTskxL4N6OkKqb1mREvmyZLbjFpoWTAmnPUHpUqc3yuky+v63mUpah7uEGwfO3FymBkSrAxgBSs1rASst9nS8M3icEBft+ea+roYBH1DLz4QNDKSIINFcpejPWHzLkCY20EW0Dn0Eaam5+Ps16aBPQ55bFX+ztrqSrRuVsFB0SuyxpXu6tA7OF28umJ+tn8345HxyjGvV84gjwzwAn+FrBrskxnSwPxnIHffht1W0m00e+8+ykKla2/J//66A352TZEIkVIfrKh8X7x/A6Y1UGItSDaOEA51Dna1OMZzsYJ7u0cBc4k7XIzJtGucVoV9tMzvhq3vmyTVwD6GEEMtPXhl3jXmklkAB4MIS1Of49tva2/KwPndmOXn2kFMEMzADtpOapIjCtR1y2uWmG9QWSyRY0bEma9dkCgZcPj56xoxcGHwaznm6s=");
+ dataKey.setString("skintrait.textureRaw",
+ "ewogICJ0aW1lc3RhbXAiIDogMTczMjgyMDQ1ODU0MCwKICAicHJvZmlsZUlkIiA6ICJmNDU3OTQ1OGE0MmQ0MzFjYmJlY2Y3MTgzNTM2ZjYzMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJCZW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2FiODM4NThlYmM4ZWU4NWMzZTU0YWIxM2FhYmZjYzFlZjJhZDQ0NmQ2YTkwMGU0NzFjM2YzM2I3ODkwNmE1YiIKICAgIH0KICB9Cn0=");
+
+ /*
+ * metadata:
+ cached-skin-uuid: f4579458-a42d-431c-bbec-f7183536f633
+ cached-skin-uuid-name: ben
+ name: ben
+ uuid: 93837773-5f4b-4337-8f2f-96a85c9665eb
+ traits:
+ type: PLAYER
+ location:
+ bodyYaw: -111.14996
+ world: bskyblock_world
+ x: -1.2024
+ y: 85.0
+ z: -1.2274
+ yaw: -111.15
+ pitch: 42.0
+ spawned: true
+ skintrait:
+ signature: QBxcn0hclFKgSvGXjivL5W6F43uPuUFQgrvumsIPZEpdzR+LKXgl+OCfdoFCvjF303mDcpvMPcAJ9XEcbA/JLbeGkcfUupw326vjsz422lABA8Uys8yR/3lKD+KXfmvtpqiuOphMLvE21vVZQb0uP9g+1XgFO6puttcB3vGmenIM7jFE3uyQ8ma44VMqv/QBz8RHCw6jn+HsuIqS/VBQ/wv+/FVDOYd+qq4nbIXEyfZK/mvRlq4+AaTskxL4N6OkKqb1mREvmyZLbjFpoWTAmnPUHpUqc3yuky+v63mUpah7uEGwfO3FymBkSrAxgBSs1rASst9nS8M3icEBft+ea+roYBH1DLz4QNDKSIINFcpejPWHzLkCY20EW0Dn0Eaam5+Ps16aBPQ55bFX+ztrqSrRuVsFB0SuyxpXu6tA7OF28umJ+tn8345HxyjGvV84gjwzwAn+FrBrskxnSwPxnIHffht1W0m00e+8+ykKla2/J//66A352TZEIkVIfrKh8X7x/A6Y1UGItSDaOEA51Dna1OMZzsYJ7u0cBc4k7XIzJtGucVoV9tMzvhq3vmyTVwD6GEEMtPXhl3jXmklkAB4MIS1Of49tva2/KwPndmOXn2kFMEMzADtpOapIjCtR1y2uWmG9QWSyRY0bEma9dkCgZcPj56xoxcGHwaznm6s=
+ textureRaw: ewogICJ0aW1lc3RhbXAiIDogMTczMjgyMDQ1ODU0MCwKICAicHJvZmlsZUlkIiA6ICJmNDU3OTQ1OGE0MmQ0MzFjYmJlY2Y3MTgzNTM2ZjYzMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJCZW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2FiODM4NThlYmM4ZWU4NWMzZTU0YWIxM2FhYmZjYzFlZjJhZDQ0NmQ2YTkwMGU0NzFjM2YzM2I3ODkwNmE1YiIKICAgIH0KICB9Cn0=
+ owner:
+ uuid: 36b2293a-ac0a-4f73-bc35-b12af97bee2b
+ traitnames: type,scoreboardtrait,location,spawned,skintrait,inventory,owner
+ navigator:
+ speedmodifier: 1.0
+ avoidwater: false
+ usedefaultstuckaction: false
+ */
+
+ config2.getKeys(true).forEach(key -> {
+ if (key.contains("metadatahdhdhdhdhhd")) {
+ String path = parentPath.isEmpty() ? key : (parentPath + "." + key);
+ Object value = config2.get(key);
+ if (value instanceof MemorySection config) {
+ insertIntoDataKey(dataKey, path, config);
+ } else {
+ BentoBox.getInstance().logDebug("Setting: " + path + " to " + value);
+ dataKey.setRaw(path, value);
+ }
+ }
+ });
+ }
+
+
public String serializeNPC(NPC npc) {
if (npc == null) {
throw new IllegalArgumentException("NPC cannot be null.");
}
+
MemoryDataKey dataKey = new MemoryDataKey();
- npc.save(dataKey); // Save NPC data into the MemoryDataKey
+ npc.save(dataKey);
// Convert MemoryDataKey to a YAML string
YamlConfiguration yaml = new YamlConfiguration();
for (Entry en : dataKey.getValuesDeep().entrySet()) {
BentoBox.getInstance().logDebug("Serial key = " + en.getKey() + " = " + en.getValue());
yaml.set(en.getKey(), en.getValue());
}
- dataKeyTest = dataKey;
return yaml.saveToString();
}
@@ -103,48 +179,22 @@ public boolean spawnCitizen(EntityType type, String serializedData, Location loc
}
// Load the serialized data into a YamlConfiguration
- YamlConfiguration yaml = YamlConfiguration.loadConfiguration(new StringReader(serializedData));
-
- // Create a new MemoryDataKey from the loaded data
- MemoryDataKey dataKey = new MemoryDataKey();
- for (String key : yaml.getKeys(true)) {
- BentoBox.getInstance().logDebug("data key " + key + " = " + yaml.get(key));
- if (key.equalsIgnoreCase("metadata") || key.equalsIgnoreCase("traits")
- || key.equalsIgnoreCase("traits.owner") || key.equalsIgnoreCase("traits.location")
- || key.equalsIgnoreCase("navigator")) {
- continue;
- }
- dataKey.setRaw(key, yaml.get(key));
- }
-
- // Get the NPC details from the serialized data
- String name = dataKey.getString("name");
- //String type = dataKey.getString("traits.type");
-
- BentoBox.getInstance().logDebug("Entity type = " + type + " name = " + name);
- if (type == null) {
- // No luck
- return false;
- }
- // Create a new NPC and load the data
- BentoBox.getInstance().logDebug("Create a new NPC and load the data");
+ DataKey npcDataKey = toDataKey(serializedData);
NPCRegistry registry = CitizensAPI.getNPCRegistry();
- try {
- NPC npc = registry.createNPC(type, name);
-
- npc.load(dataKey); // Load the serialized data into the NPC
- for (Entry en : dataKey.getValuesDeep().entrySet()) {
- BentoBox.getInstance().logDebug("loaded key " + en.getKey() + " = " + en.getValue());
- }
- boolean r = npc.spawn(location); // Spawn the NPC at the specified location
- BentoBox.getInstance().logDebug("Spawn = " + r);
- if (!r) {
- npc.load(dataKeyTest);
- BentoBox.getInstance().logDebug(npc.spawn(location)); // Spawn the NPC at the specified location
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try {
+ String mobTypeName = npcDataKey.getString("traits.type", EntityType.PLAYER.name());
+ String name = npcDataKey.getString("name", "");
+ // TODO This does not take any (version-specific) mob type migrations into account (e.g.
+ // for pig zombies). However, these migrations are currently also broken in Citizens
+ // itself (SimpleNPCDataStore does not account for mob type migrations either).
+ EntityType mobType = EntityType.valueOf(mobTypeName);
+ NPC npc = registry.createNPC(mobType, name);
+ npc.setBukkitEntityType(EntityType.valueOf(mobTypeName));
+ npc.load(npcDataKey); // Load the serialized data into the NPC
+ return npc.spawn(location);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
return false;
}
From 6b3d7a6ddec50cdd3383e670aba976fefc4a48bf Mon Sep 17 00:00:00 2001
From: tastybento
Date: Wed, 4 Dec 2024 19:29:59 -0800
Subject: [PATCH 04/10] Update to MC 1 21 4. Remove code for older versions.
---
pom.xml | 6 +++
.../PasteHandlerImpl.java | 52 -------------------
.../WorldRegeneratorImpl.java | 26 ----------
.../PasteHandlerImpl.java | 51 ------------------
.../WorldRegeneratorImpl.java | 26 ----------
.../PasteHandlerImpl.java | 52 -------------------
.../WorldRegeneratorImpl.java | 26 ----------
.../PasteHandlerImpl.java | 6 +--
.../WorldRegeneratorImpl.java | 6 +--
.../versions/ServerCompatibility.java | 38 +++++++++-----
10 files changed, 36 insertions(+), 253 deletions(-)
delete mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/PasteHandlerImpl.java
delete mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
delete mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/PasteHandlerImpl.java
delete mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
delete mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/PasteHandlerImpl.java
delete mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
rename src/main/java/world/bentobox/bentobox/nms/{v1_20_4_R0_1_SNAPSHOT => v1_21_4_R0_1_SNAPSHOT}/PasteHandlerImpl.java (92%)
rename src/main/java/world/bentobox/bentobox/nms/{v1_20_4_R0_1_SNAPSHOT => v1_21_4_R0_1_SNAPSHOT}/WorldRegeneratorImpl.java (84%)
diff --git a/pom.xml b/pom.xml
index 90bf01ed9..243d6dfbe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -234,6 +234,12 @@
${spigot.version}
provided
+
+ org.spigotmc......
+ spigot
+ 1.21.4-R0.1-SNAPSHOT
+ provided
+
org.spigotmc.....
spigot
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/PasteHandlerImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/PasteHandlerImpl.java
deleted file mode 100644
index d9cc8f9f2..000000000
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/PasteHandlerImpl.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package world.bentobox.bentobox.nms.v1_20_0_R0_1_SNAPSHOT;
-
-import java.util.concurrent.CompletableFuture;
-
-import org.bukkit.Location;
-import org.bukkit.block.Block;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
-
-import net.minecraft.core.BlockPosition;
-import net.minecraft.world.level.block.state.IBlockData;
-import net.minecraft.world.level.chunk.Chunk;
-import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
-import world.bentobox.bentobox.database.objects.Island;
-import world.bentobox.bentobox.nms.PasteHandler;
-import world.bentobox.bentobox.util.DefaultPasteUtil;
-import world.bentobox.bentobox.util.Util;
-
-public class PasteHandlerImpl implements PasteHandler {
-
-
- protected static final IBlockData AIR = ((CraftBlockData) AIR_BLOCKDATA).getState();
-
- /**
- * Set the block to the location
- *
- * @param island - island
- * @param location - location
- * @param bpBlock - blueprint block
- */
- public CompletableFuture setBlock(Island island, Location location, BlueprintBlock bpBlock) {
- return Util.getChunkAtAsync(location).thenRun(() -> {
- Block block = location.getBlock();
- // Set the block data - default is AIR
- BlockData bd = DefaultPasteUtil.createBlockData(bpBlock);
- CraftBlockData craft = (CraftBlockData) bd;
- net.minecraft.world.level.World nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
- Chunk nmsChunk = nmsWorld.d(location.getBlockX() >> 4, location.getBlockZ() >> 4);
- BlockPosition bp = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ());
- // Setting the block to air before setting to another state prevents some console errors
- nmsChunk.a(bp, AIR, false);
- nmsChunk.a(bp, craft.getState(), false);
- block.setBlockData(bd, false);
- DefaultPasteUtil.setBlockState(island, block, bpBlock);
- // Set biome
- if (bpBlock.getBiome() != null) {
- block.setBiome(bpBlock.getBiome());
- }
- });
- }
-}
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/WorldRegeneratorImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
deleted file mode 100644
index 6b85d7272..000000000
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_0_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package world.bentobox.bentobox.nms.v1_20_0_R0_1_SNAPSHOT;
-
-import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
-
-import net.minecraft.core.BlockPosition;
-import net.minecraft.world.level.World;
-import net.minecraft.world.level.chunk.Chunk;
-import world.bentobox.bentobox.nms.CopyWorldRegenerator;
-
-public class WorldRegeneratorImpl extends CopyWorldRegenerator {
-
- @Override
- public void setBlockInNativeChunk(org.bukkit.Chunk chunk, int x, int y, int z, BlockData blockData,
- boolean applyPhysics) {
- CraftBlockData craft = (CraftBlockData) blockData;
- World nmsWorld = ((CraftWorld) chunk.getWorld()).getHandle();
- Chunk nmsChunk = nmsWorld.d(chunk.getX(), chunk.getZ());
- BlockPosition bp = new BlockPosition((chunk.getX() << 4) + x, y, (chunk.getZ() << 4) + z);
- // Setting the block to air before setting to another state prevents some console errors
- nmsChunk.a(bp, PasteHandlerImpl.AIR, applyPhysics);
- nmsChunk.a(bp, craft.getState(), applyPhysics);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/PasteHandlerImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/PasteHandlerImpl.java
deleted file mode 100644
index 483025c52..000000000
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/PasteHandlerImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package world.bentobox.bentobox.nms.v1_20_1_R0_1_SNAPSHOT;
-
-import java.util.concurrent.CompletableFuture;
-
-import org.bukkit.Location;
-import org.bukkit.block.Block;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
-
-import net.minecraft.core.BlockPosition;
-import net.minecraft.world.level.block.state.IBlockData;
-import net.minecraft.world.level.chunk.Chunk;
-import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
-import world.bentobox.bentobox.database.objects.Island;
-import world.bentobox.bentobox.nms.PasteHandler;
-import world.bentobox.bentobox.util.DefaultPasteUtil;
-import world.bentobox.bentobox.util.Util;
-
-public class PasteHandlerImpl implements PasteHandler {
-
- protected static final IBlockData AIR = ((CraftBlockData) AIR_BLOCKDATA).getState();
-
- /**
- * Set the block to the location
- *
- * @param island - island
- * @param location - location
- * @param bpBlock - blueprint block
- */
- public CompletableFuture setBlock(Island island, Location location, BlueprintBlock bpBlock) {
- return Util.getChunkAtAsync(location).thenRun(() -> {
- Block block = location.getBlock();
- // Set the block data - default is AIR
- BlockData bd = DefaultPasteUtil.createBlockData(bpBlock);
- CraftBlockData craft = (CraftBlockData) bd;
- net.minecraft.world.level.World nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
- Chunk nmsChunk = nmsWorld.d(location.getBlockX() >> 4, location.getBlockZ() >> 4);
- BlockPosition bp = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ());
- // Setting the block to air before setting to another state prevents some console errors
- nmsChunk.a(bp, AIR, false);
- nmsChunk.a(bp, craft.getState(), false);
- block.setBlockData(bd, false);
- DefaultPasteUtil.setBlockState(island, block, bpBlock);
- // Set biome
- if (bpBlock.getBiome() != null) {
- block.setBiome(bpBlock.getBiome());
- }
- });
- }
-}
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/WorldRegeneratorImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
deleted file mode 100644
index d15d4809b..000000000
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_1_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package world.bentobox.bentobox.nms.v1_20_1_R0_1_SNAPSHOT;
-
-import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
-
-import net.minecraft.core.BlockPosition;
-import net.minecraft.world.level.World;
-import net.minecraft.world.level.chunk.Chunk;
-import world.bentobox.bentobox.nms.CopyWorldRegenerator;
-
-public class WorldRegeneratorImpl extends CopyWorldRegenerator {
-
- @Override
- public void setBlockInNativeChunk(org.bukkit.Chunk chunk, int x, int y, int z, BlockData blockData,
- boolean applyPhysics) {
- CraftBlockData craft = (CraftBlockData) blockData;
- World nmsWorld = ((CraftWorld) chunk.getWorld()).getHandle();
- Chunk nmsChunk = nmsWorld.d(chunk.getX(), chunk.getZ());
- BlockPosition bp = new BlockPosition((chunk.getX() << 4) + x, y, (chunk.getZ() << 4) + z);
- // Setting the block to air before setting to another state prevents some console errors
- nmsChunk.a(bp, PasteHandlerImpl.AIR, applyPhysics);
- nmsChunk.a(bp, craft.getState(), applyPhysics);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/PasteHandlerImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/PasteHandlerImpl.java
deleted file mode 100644
index 49efdc370..000000000
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/PasteHandlerImpl.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package world.bentobox.bentobox.nms.v1_20_6_R0_1_SNAPSHOT;
-
-import java.util.concurrent.CompletableFuture;
-
-import org.bukkit.Location;
-import org.bukkit.block.Block;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
-
-import net.minecraft.core.BlockPosition;
-import net.minecraft.world.level.block.state.IBlockData;
-import net.minecraft.world.level.chunk.Chunk;
-import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
-import world.bentobox.bentobox.database.objects.Island;
-import world.bentobox.bentobox.nms.PasteHandler;
-import world.bentobox.bentobox.util.DefaultPasteUtil;
-import world.bentobox.bentobox.util.Util;
-
-public class PasteHandlerImpl implements PasteHandler {
-
- protected static final IBlockData AIR = ((CraftBlockData) AIR_BLOCKDATA).getState();
-
- /**
- * Set the block to the location
- *
- * @param island - island
- * @param location - location
- * @param bpBlock - blueprint block
- */
- @Override
- public CompletableFuture setBlock(Island island, Location location, BlueprintBlock bpBlock) {
- return Util.getChunkAtAsync(location).thenRun(() -> {
- Block block = location.getBlock();
- // Set the block data - default is AIR
- BlockData bd = DefaultPasteUtil.createBlockData(bpBlock);
- CraftBlockData craft = (CraftBlockData) bd;
- net.minecraft.world.level.World nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
- Chunk nmsChunk = nmsWorld.d(location.getBlockX() >> 4, location.getBlockZ() >> 4);
- BlockPosition bp = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ());
- // Setting the block to air before setting to another state prevents some console errors
- nmsChunk.a(bp, AIR, false);
- nmsChunk.a(bp, craft.getState(), false);
- block.setBlockData(bd, false);
- DefaultPasteUtil.setBlockState(island, block, bpBlock);
- // Set biome
- if (bpBlock.getBiome() != null) {
- block.setBiome(bpBlock.getBiome());
- }
- });
- }
-}
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/WorldRegeneratorImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
deleted file mode 100644
index fbff31665..000000000
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_6_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package world.bentobox.bentobox.nms.v1_20_6_R0_1_SNAPSHOT;
-
-import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
-
-import net.minecraft.core.BlockPosition;
-import net.minecraft.world.level.World;
-import net.minecraft.world.level.chunk.Chunk;
-import world.bentobox.bentobox.nms.CopyWorldRegenerator;
-
-public class WorldRegeneratorImpl extends CopyWorldRegenerator {
-
- @Override
- public void setBlockInNativeChunk(org.bukkit.Chunk chunk, int x, int y, int z, BlockData blockData,
- boolean applyPhysics) {
- CraftBlockData craft = (CraftBlockData) blockData;
- World nmsWorld = ((CraftWorld) chunk.getWorld()).getHandle();
- Chunk nmsChunk = nmsWorld.d(chunk.getX(), chunk.getZ());
- BlockPosition bp = new BlockPosition((chunk.getX() << 4) + x, y, (chunk.getZ() << 4) + z);
- // Setting the block to air before setting to another state prevents some console errors
- nmsChunk.a(bp, PasteHandlerImpl.AIR, applyPhysics);
- nmsChunk.a(bp, craft.getState(), applyPhysics);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_4_R0_1_SNAPSHOT/PasteHandlerImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_21_4_R0_1_SNAPSHOT/PasteHandlerImpl.java
similarity index 92%
rename from src/main/java/world/bentobox/bentobox/nms/v1_20_4_R0_1_SNAPSHOT/PasteHandlerImpl.java
rename to src/main/java/world/bentobox/bentobox/nms/v1_21_4_R0_1_SNAPSHOT/PasteHandlerImpl.java
index af6a83d7a..e0096f298 100644
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_4_R0_1_SNAPSHOT/PasteHandlerImpl.java
+++ b/src/main/java/world/bentobox/bentobox/nms/v1_21_4_R0_1_SNAPSHOT/PasteHandlerImpl.java
@@ -1,12 +1,12 @@
-package world.bentobox.bentobox.nms.v1_20_4_R0_1_SNAPSHOT;
+package world.bentobox.bentobox.nms.v1_21_4_R0_1_SNAPSHOT;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
+import org.bukkit.craftbukkit.v1_21_R3.CraftWorld;
+import org.bukkit.craftbukkit.v1_21_R3.block.data.CraftBlockData;
import net.minecraft.core.BlockPosition;
import net.minecraft.world.level.block.state.IBlockData;
diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_20_4_R0_1_SNAPSHOT/WorldRegeneratorImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_21_4_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
similarity index 84%
rename from src/main/java/world/bentobox/bentobox/nms/v1_20_4_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
rename to src/main/java/world/bentobox/bentobox/nms/v1_21_4_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
index f259a92bb..ca4215070 100644
--- a/src/main/java/world/bentobox/bentobox/nms/v1_20_4_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
+++ b/src/main/java/world/bentobox/bentobox/nms/v1_21_4_R0_1_SNAPSHOT/WorldRegeneratorImpl.java
@@ -1,8 +1,8 @@
-package world.bentobox.bentobox.nms.v1_20_4_R0_1_SNAPSHOT;
+package world.bentobox.bentobox.nms.v1_21_4_R0_1_SNAPSHOT;
import org.bukkit.block.data.BlockData;
-import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
-import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
+import org.bukkit.craftbukkit.v1_21_R3.CraftWorld;
+import org.bukkit.craftbukkit.v1_21_R3.block.data.CraftBlockData;
import net.minecraft.core.BlockPosition;
import net.minecraft.world.level.World;
diff --git a/src/main/java/world/bentobox/bentobox/versions/ServerCompatibility.java b/src/main/java/world/bentobox/bentobox/versions/ServerCompatibility.java
index 2b356e31e..a5566b07a 100644
--- a/src/main/java/world/bentobox/bentobox/versions/ServerCompatibility.java
+++ b/src/main/java/world/bentobox/bentobox/versions/ServerCompatibility.java
@@ -197,23 +197,23 @@ public enum ServerVersion {
/**
* @since 1.21.0
*/
- V1_19(Compatibility.COMPATIBLE),
+ V1_19(Compatibility.INCOMPATIBLE),
/**
* @since 1.21.0
*/
- V1_19_1(Compatibility.COMPATIBLE),
+ V1_19_1(Compatibility.INCOMPATIBLE),
/**
* @since 1.21.0
*/
- V1_19_2(Compatibility.COMPATIBLE),
+ V1_19_2(Compatibility.INCOMPATIBLE),
/**
* @since 1.22.0
*/
- V1_19_3(Compatibility.COMPATIBLE),
+ V1_19_3(Compatibility.INCOMPATIBLE),
/**
* @since 1.22.1
*/
- V1_19_4(Compatibility.COMPATIBLE),
+ V1_19_4(Compatibility.INCOMPATIBLE),
/**
* @since 1.24.0
*/
@@ -221,40 +221,50 @@ public enum ServerVersion {
/**
* @since 1.24.0
*/
- V1_20_1(Compatibility.COMPATIBLE),
+ V1_20_1(Compatibility.INCOMPATIBLE),
/**
* @since 2.0.0
*/
- V1_20_2(Compatibility.COMPATIBLE),
+ V1_20_2(Compatibility.INCOMPATIBLE),
/**
* @since 2.0.0
*/
- V1_20_3(Compatibility.COMPATIBLE),
+ V1_20_3(Compatibility.INCOMPATIBLE),
/**
* @since 2.0.0
*/
- V1_20_4(Compatibility.COMPATIBLE),
+ V1_20_4(Compatibility.INCOMPATIBLE),
/**
* @since 2.4.0
*/
- V1_20_5(Compatibility.COMPATIBLE),
+ V1_20_5(Compatibility.INCOMPATIBLE),
/**
* @since 2.4.0
*/
- V1_20_6(Compatibility.COMPATIBLE),
+ V1_20_6(Compatibility.INCOMPATIBLE),
/**
* @since 2.4.0
*/
- V1_21(Compatibility.COMPATIBLE),
+ V1_21(Compatibility.INCOMPATIBLE),
/**
* @since 2.5.0
*/
- V1_21_1(Compatibility.COMPATIBLE),
+ V1_21_1(Compatibility.INCOMPATIBLE),
/**
* @since 2.7.0
*/
- V1_21_2(Compatibility.INCOMPATIBLE), V1_21_3(Compatibility.COMPATIBLE);
+ V1_21_2(Compatibility.INCOMPATIBLE),
+
+ /**
+ * @since 3.0.0
+ */
+ V1_21_3(Compatibility.COMPATIBLE),
+
+ /**
+ * @since 3.0.1
+ */
+ V1_21_4(Compatibility.COMPATIBLE),;
private final Compatibility compatibility;
From b4a802d746b3b5c841e1df24579a84754d005e5d Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 7 Dec 2024 13:02:25 -0800
Subject: [PATCH 05/10] Add support for FancyNpcs
---
pom.xml | 24 +-
.../world/bentobox/bentobox/BentoBox.java | 7 +-
.../blueprints/BlueprintClipboard.java | 14 +-
.../dataobjects/BlueprintEntity.java | 16 +-
.../bentobox/bentobox/hooks/CitizensHook.java | 215 -------------
.../bentobox/hooks/FancyNpcsHook.java | 293 ++++++++++++++++++
.../bentobox/managers/IslandsManager.java | 1 -
.../bentobox/util/DefaultPasteUtil.java | 27 +-
8 files changed, 336 insertions(+), 261 deletions(-)
delete mode 100644 src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
create mode 100644 src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java
diff --git a/pom.xml b/pom.xml
index 845415559..c8ed60cb8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -192,10 +192,11 @@
clojars
https://repo.clojars.org/
-
+
- citizens-repo
- https://maven.citizensnpcs.co/repo
+ fancyplugins-releases
+ FancyPlugins Repository
+ https://repo.fancyplugins.de/releases
@@ -398,19 +399,12 @@
1.1.13
compile
-
-
- net.citizensnpcs
- citizens-main
- 2.0.35-SNAPSHOT
- jar
+
+
+ de.oliver
+ FancyNpcs
+ 2.4.0
provided
-
-
- *
- *
-
-
diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java
index ae4f06a60..ff315d7de 100644
--- a/src/main/java/world/bentobox/bentobox/BentoBox.java
+++ b/src/main/java/world/bentobox/bentobox/BentoBox.java
@@ -19,12 +19,13 @@
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
+import world.bentobox.bentobox.api.hooks.Hook;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.Notifier;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.commands.BentoBoxCommand;
import world.bentobox.bentobox.database.DatabaseSetup;
-import world.bentobox.bentobox.hooks.CitizensHook;
+import world.bentobox.bentobox.hooks.FancyNpcsHook;
import world.bentobox.bentobox.hooks.ItemsAdderHook;
import world.bentobox.bentobox.hooks.MultipaperHook;
import world.bentobox.bentobox.hooks.MultiverseCoreHook;
@@ -193,8 +194,8 @@ private void completeSetup(long loadTime) {
hooksManager.registerHook(new VaultHook());
- // Citizens
- hooksManager.registerHook(new CitizensHook());
+ // FancyNpcs
+ hooksManager.registerHook(new FancyNpcsHook());
// MythicMobs
hooksManager.registerHook(new MythicMobsHook());
diff --git a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java
index 315ef66e8..dc10da175 100644
--- a/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java
+++ b/src/main/java/world/bentobox/bentobox/blueprints/BlueprintClipboard.java
@@ -43,7 +43,7 @@
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
-import world.bentobox.bentobox.hooks.CitizensHook;
+import world.bentobox.bentobox.hooks.FancyNpcsHook;
import world.bentobox.bentobox.hooks.MythicMobsHook;
/**
@@ -70,7 +70,7 @@ public class BlueprintClipboard {
private final Map bpBlocks = new LinkedHashMap<>();
private final BentoBox plugin = BentoBox.getInstance();
private Optional mmh;
- private Optional ch;
+ private Optional npc;
/**
* Create a clipboard for blueprint
@@ -83,7 +83,8 @@ public BlueprintClipboard(@NonNull Blueprint blueprint) {
public BlueprintClipboard() {
// Citizens Hook
- ch = plugin.getHooks().getHook("Citizens").filter(CitizensHook.class::isInstance).map(CitizensHook.class::cast);
+ npc = plugin.getHooks().getHook("FancyNpcs").filter(FancyNpcsHook.class::isInstance)
+ .map(FancyNpcsHook.class::cast);
// MythicMobs Hook
mmh = plugin.getHooks().getHook("MythicMobs").filter(MythicMobsHook.class::isInstance)
.map(MythicMobsHook.class::cast);
@@ -137,10 +138,10 @@ public boolean copy(User user, boolean copyAir, boolean copyBiome) {
private void copyAsync(World world, User user, List vectorsToCopy, int speed, boolean copyAir, boolean copyBiome) {
copying = false;
- // Citizens
- if (ch.isPresent()) {
+ // FancyNpcs
+ if (npc.isPresent()) {
// Add all the citizens for the area in one go. This is pretty fast.
- bpEntities.putAll(ch.get().getCitizensInArea(world, vectorsToCopy, origin));
+ bpEntities.putAll(npc.get().getNpcsInArea(world, vectorsToCopy, origin));
}
// Repeating copy task
@@ -308,7 +309,6 @@ private BlueprintCreatureSpawner getSpawner(CreatureSpawner spawner) {
private List setEntities(List ents) {
List bpEnts = new ArrayList<>();
for (Entity entity : ents) {
- BentoBox.getInstance().logDebug("Etity = " + entity);
BlueprintEntity bpe = new BlueprintEntity();
bpe.setType(entity.getType());
diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java
index 3c1e1959a..2ce285fee 100644
--- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java
+++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java
@@ -24,9 +24,9 @@
*/
public class BlueprintEntity {
- // Citizens storage
+ // Npc storage
@Expose
- private String citizen;
+ private String npc;
// MythicMobs storage
public record MythicMobRecord(String type, String displayName, double level, float power, String stance) {
@@ -310,22 +310,22 @@ public void setMythicMobsRecord(MythicMobRecord mmr) {
}
/**
- * @return the citizen
+ * @return the npc
*/
- public String getCitizen() {
- return citizen;
+ public String getNpc() {
+ return npc;
}
/**
* @param citizen the citizen to set
*/
- public void setCitizen(String citizen) {
- this.citizen = citizen;
+ public void setNpc(String citizen) {
+ this.npc = citizen;
}
@Override
public String toString() {
- return "BlueprintEntity [" + (citizen != null ? "citizen=" + citizen + ", " : "")
+ return "BlueprintEntity [" + (npc != null ? "npc=" + npc + ", " : "")
+ (MMtype != null ? "MMtype=" + MMtype + ", " : "")
+ (MMLevel != null ? "MMLevel=" + MMLevel + ", " : "")
+ (MMStance != null ? "MMStance=" + MMStance + ", " : "")
diff --git a/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java b/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
deleted file mode 100644
index e7d295f4e..000000000
--- a/src/main/java/world/bentobox/bentobox/hooks/CitizensHook.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package world.bentobox.bentobox.hooks;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.World;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.MemorySection;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.EntityType;
-import org.bukkit.util.Vector;
-import org.eclipse.jdt.annotation.Nullable;
-
-import net.citizensnpcs.api.CitizensAPI;
-import net.citizensnpcs.api.npc.NPC;
-import net.citizensnpcs.api.npc.NPCRegistry;
-import net.citizensnpcs.api.util.DataKey;
-import net.citizensnpcs.api.util.MemoryDataKey;
-import world.bentobox.bentobox.BentoBox;
-import world.bentobox.bentobox.api.hooks.Hook;
-import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
-
-/**
- * Provides copy and pasting of Citizens in blueprints
- *
- * @author tastybento
- * @since 3.1.0
- */
-public class CitizensHook extends Hook {
-
- public CitizensHook() {
- super("Citizens", Material.PLAYER_HEAD);
- }
-
- public static DataKey toDataKey(String serializedData) {
- DataKey dataKey = new MemoryDataKey();
- YamlConfiguration y = new YamlConfiguration();
- try {
- y.loadFromString(serializedData);
- } catch (InvalidConfigurationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- insertIntoDataKey(dataKey, "", y);
- return dataKey;
- }
-
- private static void insertIntoDataKey(DataKey dataKey, String parentPath, ConfigurationSection config2) {
- // Manually set the keys and see where it breaks
- dataKey.setString("name", "bentest");
- dataKey.setString("uuid", UUID.randomUUID().toString());
- dataKey.setString("traits.type", "PLAYER");
- dataKey.setDouble("traits.location.bodyYaw", -111.14996);
- dataKey.setDouble("traits.location.x", 0.0);
- dataKey.setDouble("traits.location.y", 0.0);
- dataKey.setDouble("traits.location.z", 0.0);
- dataKey.setDouble("traits.location.yaw", -111.15);
- dataKey.setDouble("traits.location.pitch", 42.0);
- dataKey.setBoolean("spawned", true);
- dataKey.setString("traitnames", "type,location,spawned");
- dataKey.setString("metadata.cached-skin-uuid", "f4579458-a42d-431c-bbec-f7183536f633");
- dataKey.setString("skintrait.signature",
- "QBxcn0hclFKgSvGXjivL5W6F43uPuUFQgrvumsIPZEpdzR+LKXgl+OCfdoFCvjF303mDcpvMPcAJ9XEcbA/JLbeGkcfUupw326vjsz422lABA8Uys8yR/3lKD+KXfmvtpqiuOphMLvE21vVZQb0uP9g+1XgFO6puttcB3vGmenIM7jFE3uyQ8ma44VMqv/QBz8RHCw6jn+HsuIqS/VBQ/wv+/FVDOYd+qq4nbIXEyfZK/mvRlq4+AaTskxL4N6OkKqb1mREvmyZLbjFpoWTAmnPUHpUqc3yuky+v63mUpah7uEGwfO3FymBkSrAxgBSs1rASst9nS8M3icEBft+ea+roYBH1DLz4QNDKSIINFcpejPWHzLkCY20EW0Dn0Eaam5+Ps16aBPQ55bFX+ztrqSrRuVsFB0SuyxpXu6tA7OF28umJ+tn8345HxyjGvV84gjwzwAn+FrBrskxnSwPxnIHffht1W0m00e+8+ykKla2/J//66A352TZEIkVIfrKh8X7x/A6Y1UGItSDaOEA51Dna1OMZzsYJ7u0cBc4k7XIzJtGucVoV9tMzvhq3vmyTVwD6GEEMtPXhl3jXmklkAB4MIS1Of49tva2/KwPndmOXn2kFMEMzADtpOapIjCtR1y2uWmG9QWSyRY0bEma9dkCgZcPj56xoxcGHwaznm6s=");
- dataKey.setString("skintrait.textureRaw",
- "ewogICJ0aW1lc3RhbXAiIDogMTczMjgyMDQ1ODU0MCwKICAicHJvZmlsZUlkIiA6ICJmNDU3OTQ1OGE0MmQ0MzFjYmJlY2Y3MTgzNTM2ZjYzMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJCZW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2FiODM4NThlYmM4ZWU4NWMzZTU0YWIxM2FhYmZjYzFlZjJhZDQ0NmQ2YTkwMGU0NzFjM2YzM2I3ODkwNmE1YiIKICAgIH0KICB9Cn0=");
-
- /*
- * metadata:
- cached-skin-uuid: f4579458-a42d-431c-bbec-f7183536f633
- cached-skin-uuid-name: ben
- name: ben
- uuid: 93837773-5f4b-4337-8f2f-96a85c9665eb
- traits:
- type: PLAYER
- location:
- bodyYaw: -111.14996
- world: bskyblock_world
- x: -1.2024
- y: 85.0
- z: -1.2274
- yaw: -111.15
- pitch: 42.0
- spawned: true
- skintrait:
- signature: QBxcn0hclFKgSvGXjivL5W6F43uPuUFQgrvumsIPZEpdzR+LKXgl+OCfdoFCvjF303mDcpvMPcAJ9XEcbA/JLbeGkcfUupw326vjsz422lABA8Uys8yR/3lKD+KXfmvtpqiuOphMLvE21vVZQb0uP9g+1XgFO6puttcB3vGmenIM7jFE3uyQ8ma44VMqv/QBz8RHCw6jn+HsuIqS/VBQ/wv+/FVDOYd+qq4nbIXEyfZK/mvRlq4+AaTskxL4N6OkKqb1mREvmyZLbjFpoWTAmnPUHpUqc3yuky+v63mUpah7uEGwfO3FymBkSrAxgBSs1rASst9nS8M3icEBft+ea+roYBH1DLz4QNDKSIINFcpejPWHzLkCY20EW0Dn0Eaam5+Ps16aBPQ55bFX+ztrqSrRuVsFB0SuyxpXu6tA7OF28umJ+tn8345HxyjGvV84gjwzwAn+FrBrskxnSwPxnIHffht1W0m00e+8+ykKla2/J//66A352TZEIkVIfrKh8X7x/A6Y1UGItSDaOEA51Dna1OMZzsYJ7u0cBc4k7XIzJtGucVoV9tMzvhq3vmyTVwD6GEEMtPXhl3jXmklkAB4MIS1Of49tva2/KwPndmOXn2kFMEMzADtpOapIjCtR1y2uWmG9QWSyRY0bEma9dkCgZcPj56xoxcGHwaznm6s=
- textureRaw: ewogICJ0aW1lc3RhbXAiIDogMTczMjgyMDQ1ODU0MCwKICAicHJvZmlsZUlkIiA6ICJmNDU3OTQ1OGE0MmQ0MzFjYmJlY2Y3MTgzNTM2ZjYzMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJCZW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2FiODM4NThlYmM4ZWU4NWMzZTU0YWIxM2FhYmZjYzFlZjJhZDQ0NmQ2YTkwMGU0NzFjM2YzM2I3ODkwNmE1YiIKICAgIH0KICB9Cn0=
- owner:
- uuid: 36b2293a-ac0a-4f73-bc35-b12af97bee2b
- traitnames: type,scoreboardtrait,location,spawned,skintrait,inventory,owner
- navigator:
- speedmodifier: 1.0
- avoidwater: false
- usedefaultstuckaction: false
- */
-
- config2.getKeys(true).forEach(key -> {
- if (key.contains("metadatahdhdhdhdhhd")) {
- String path = parentPath.isEmpty() ? key : (parentPath + "." + key);
- Object value = config2.get(key);
- if (value instanceof MemorySection config) {
- insertIntoDataKey(dataKey, path, config);
- } else {
- BentoBox.getInstance().logDebug("Setting: " + path + " to " + value);
- dataKey.setRaw(path, value);
- }
- }
- });
- }
-
-
- public String serializeNPC(NPC npc) {
- if (npc == null) {
- throw new IllegalArgumentException("NPC cannot be null.");
- }
-
- MemoryDataKey dataKey = new MemoryDataKey();
- npc.save(dataKey);
- // Convert MemoryDataKey to a YAML string
- YamlConfiguration yaml = new YamlConfiguration();
- for (Entry en : dataKey.getValuesDeep().entrySet()) {
- BentoBox.getInstance().logDebug("Serial key = " + en.getKey() + " = " + en.getValue());
- yaml.set(en.getKey(), en.getValue());
- }
- return yaml.saveToString();
- }
-
- /**
- * Get a map of serialized Citizens that are in a set of locations
- * @param world world where this occurs
- * @param vectorsToCopy list of locations in that world as vectors
- * @param origin
- * @return map
- */
- public Map> getCitizensInArea(World world, List vectorsToCopy,
- @Nullable Vector origin) {
- Map> bpEntities = new HashMap<>();
- for (NPC npc : CitizensAPI.getNPCRegistry()) {
- if (npc.isSpawned()) {
- Location npcLocation = npc.getEntity().getLocation();
- Vector spot = new Vector(npcLocation.getBlockX(), npcLocation.getBlockY(), npcLocation.getBlockZ());
- if (npcLocation.getWorld().equals(world) && vectorsToCopy.contains(spot)) {
- BlueprintEntity cit = new BlueprintEntity();
- cit.setType(npc.getEntity().getType()); // Must be set to be pasted
- cit.setCitizen(serializeNPC(npc));
- // Retrieve or create the list, then add the entity
- List entities = bpEntities.getOrDefault(spot, new ArrayList<>());
- entities.add(cit);
- // Create position
- Vector origin2 = origin == null ? new Vector(0, 0, 0) : origin;
- int x = spot.getBlockX() - origin2.getBlockX();
- int y = spot.getBlockY() - origin2.getBlockY();
- int z = spot.getBlockZ() - origin2.getBlockZ();
- Vector pos = new Vector(x, y, z);
- // Store
- bpEntities.put(pos, entities); // Update the map
- }
- }
- }
- return bpEntities;
- }
-
- /**
- * Spawn a Citizen
- * @param serializedData serialized data
- * @param location location
- * @return true if spawn is successful
- */
- public boolean spawnCitizen(EntityType type, String serializedData, Location location) {
- BentoBox.getInstance().logDebug("spawn Citizen at " + location + " with this data " + serializedData);
- if (serializedData == null || location == null) {
- throw new IllegalArgumentException("Serialized data and location cannot be null.");
- }
-
- // Load the serialized data into a YamlConfiguration
- DataKey npcDataKey = toDataKey(serializedData);
- NPCRegistry registry = CitizensAPI.getNPCRegistry();
- try {
- String mobTypeName = npcDataKey.getString("traits.type", EntityType.PLAYER.name());
- String name = npcDataKey.getString("name", "");
- // TODO This does not take any (version-specific) mob type migrations into account (e.g.
- // for pig zombies). However, these migrations are currently also broken in Citizens
- // itself (SimpleNPCDataStore does not account for mob type migrations either).
- EntityType mobType = EntityType.valueOf(mobTypeName);
- NPC npc = registry.createNPC(mobType, name);
- npc.setBukkitEntityType(EntityType.valueOf(mobTypeName));
- npc.load(npcDataKey); // Load the serialized data into the NPC
- return npc.spawn(location);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
-
-
- @Override
- public boolean hook() {
- boolean hooked = this.isPluginAvailable();
- if (!hooked) {
- BentoBox.getInstance().logError("Could not hook into Citizens");
- }
- return hooked; // The hook process shouldn't fail
- }
-
- @Override
- public String getFailureCause() {
- return null; // The hook process shouldn't fail
- }
-}
diff --git a/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java b/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java
new file mode 100644
index 000000000..acc5ba7d8
--- /dev/null
+++ b/src/main/java/world/bentobox/bentobox/hooks/FancyNpcsHook.java
@@ -0,0 +1,293 @@
+package world.bentobox.bentobox.hooks;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.EntityType;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.Vector;
+import org.eclipse.jdt.annotation.Nullable;
+
+import de.oliver.fancynpcs.api.FancyNpcsPlugin;
+import de.oliver.fancynpcs.api.Npc;
+import de.oliver.fancynpcs.api.NpcAttribute;
+import de.oliver.fancynpcs.api.NpcData;
+import de.oliver.fancynpcs.api.actions.ActionTrigger;
+import de.oliver.fancynpcs.api.actions.NpcAction;
+import de.oliver.fancynpcs.api.utils.NpcEquipmentSlot;
+import de.oliver.fancynpcs.api.utils.SkinFetcher;
+import net.kyori.adventure.text.format.NamedTextColor;
+import world.bentobox.bentobox.BentoBox;
+import world.bentobox.bentobox.api.hooks.Hook;
+import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
+
+/**
+ * Provides copy and pasting of FancyNPCs in blueprints
+ *
+ * @author tastybento
+ * @since 3.1.0
+ */
+public class FancyNpcsHook extends Hook {
+
+ public FancyNpcsHook() {
+ super("FancyNpcs", Material.PLAYER_HEAD);
+ }
+
+ public String serializeNPC(Npc npc, Vector origin) {
+ if (npc == null) {
+ throw new IllegalArgumentException("NPC cannot be null.");
+ }
+ YamlConfiguration npcConfig = new YamlConfiguration();
+ NpcData data = npc.getData();
+ npcConfig.set("name", data.getName()); // Stored just for reference
+ npcConfig.set("creator", data.getCreator().toString());
+ npcConfig.set("displayName", data.getDisplayName());
+ npcConfig.set("type", data.getType().name());
+ npcConfig.set("location.world", data.getLocation().getWorld().getName()); // This will not be used
+ // Location is stored relative to the origin, and just stored for reference. x,y,z are not used
+ npcConfig.set("location.x", data.getLocation().getX() - origin.getBlockX());
+ npcConfig.set("location.y", data.getLocation().getY() - origin.getBlockY());
+ npcConfig.set("location.z", data.getLocation().getZ() - origin.getBlockZ());
+ // Only yaw and pitch are used
+ npcConfig.set("location.yaw", data.getLocation().getYaw());
+ npcConfig.set("location.pitch", data.getLocation().getPitch());
+ npcConfig.set("showInTab", data.isShowInTab());
+ npcConfig.set("spawnEntity", data.isSpawnEntity());
+ npcConfig.set("collidable", data.isCollidable());
+ npcConfig.set("glowing", data.isGlowing());
+ npcConfig.set("glowingColor", data.getGlowingColor().toString());
+ npcConfig.set("turnToPlayer", data.isTurnToPlayer());
+ npcConfig.set("messages", null);
+ npcConfig.set("playerCommands", null);
+ npcConfig.set("serverCommands", null);
+ npcConfig.set("sendMessagesRandomly", null);
+ npcConfig.set("interactionCooldown", data.getInteractionCooldown());
+ npcConfig.set("scale", data.getScale());
+
+ if (data.getSkin() != null) {
+ npcConfig.set("skin.identifier", data.getSkin().identifier());
+ } else {
+ npcConfig.set("skin.identifier", null);
+ }
+ npcConfig.set("skin.mirrorSkin", data.isMirrorSkin());
+
+ if (data.getEquipment() != null) {
+ for (Entry entry : data.getEquipment().entrySet()) {
+ npcConfig.set("equipment." + entry.getKey().name(), entry.getValue());
+ }
+ }
+
+ for (NpcAttribute attribute : FancyNpcsPlugin.get().getAttributeManager()
+ .getAllAttributesForEntityType(data.getType())) {
+ String value = data.getAttributes().getOrDefault(attribute, null);
+ npcConfig.set("attributes." + attribute.getName(), value);
+ }
+
+ npcConfig.set("actions", null);
+ for (Map.Entry> entry : npc.getData().getActions().entrySet()) {
+ for (NpcAction.NpcActionData actionData : entry.getValue()) {
+ if (actionData == null) {
+ continue;
+ }
+
+ npcConfig.set("actions." + entry.getKey().name() + "." + actionData.order() + ".action",
+ actionData.action().getName());
+ npcConfig.set("actions." + entry.getKey().name() + "." + actionData.order() + ".value",
+ actionData.value());
+ }
+ }
+
+ return npcConfig.saveToString();
+ }
+
+ public boolean spawnNpc(String yaml, Location pos) throws InvalidConfigurationException {
+ YamlConfiguration npcConfig = new YamlConfiguration();
+ npcConfig.loadFromString(yaml);
+
+ String name = UUID.randomUUID().toString(); // Create a unique name
+
+ UUID creator = UUID.randomUUID(); // Random creator
+
+ String displayName = npcConfig.getString("displayName", "");
+ EntityType type = EntityType.valueOf(npcConfig.getString("type", "PLAYER").toUpperCase(Locale.ENGLISH));
+
+ // Create the spawn location
+ Location location = null;
+ double x = pos.getBlockX();
+ double y = pos.getBlockY();
+ double z = pos.getBlockZ();
+ // Add in the yaw and pitch
+ float yaw = (float) npcConfig.getDouble("location.yaw");
+ float pitch = (float) npcConfig.getDouble("location.pitch");
+
+ location = new Location(pos.getWorld(), x, y, z, yaw, pitch);
+
+
+ String skinIdentifier = npcConfig.getString("skin.identifier", npcConfig.getString("skin.uuid", ""));
+ SkinFetcher.SkinData skin = null;
+ if (!skinIdentifier.isEmpty()) {
+ skin = new SkinFetcher.SkinData(skinIdentifier, "", "");
+ }
+
+ if (npcConfig.isSet("skin.value") && npcConfig.isSet("skin.signature")) {
+
+ String value = npcConfig.getString("skin.value");
+ String signature = npcConfig.getString("skin.signature");
+
+ if (value != null && !value.isEmpty() && signature != null && !signature.isEmpty()) {
+ skin = new SkinFetcher.SkinData(skinIdentifier, value, signature);
+ SkinFetcher.SkinData oldSkinData = new SkinFetcher.SkinData(skinIdentifier, value, signature);
+ SkinFetcher.skinCache.put(skinIdentifier, oldSkinData);
+ FancyNpcsPlugin.get().getSkinCache().upsert(new SkinFetcher.SkinCacheData(oldSkinData,
+ System.currentTimeMillis(), 1000 * 60 * 60 * 24));
+ }
+ }
+
+ boolean mirrorSkin = npcConfig.getBoolean("skin.mirrorSkin");
+
+ boolean showInTab = npcConfig.getBoolean("showInTab");
+ boolean spawnEntity = npcConfig.getBoolean("spawnEntity");
+ boolean collidable = npcConfig.getBoolean("collidable", true);
+ boolean glowing = npcConfig.getBoolean("glowing");
+ NamedTextColor glowingColor = NamedTextColor.NAMES
+ .value(npcConfig.getString("glowingColor", "white"));
+ boolean turnToPlayer = npcConfig.getBoolean("turnToPlayer");
+
+ Map> actions = new ConcurrentHashMap<>();
+
+ ConfigurationSection actiontriggerSection = npcConfig.getConfigurationSection("actions");
+ if (actiontriggerSection != null) {
+ actiontriggerSection.getKeys(false).forEach(trigger -> {
+ ActionTrigger actionTrigger = ActionTrigger.getByName(trigger);
+ if (actionTrigger == null) {
+ BentoBox.getInstance().logWarning("Could not find action trigger: " + trigger);
+ return;
+ }
+
+ List actionList = new ArrayList<>();
+ ConfigurationSection actionsSection = npcConfig.getConfigurationSection("actions." + trigger);
+ if (actionsSection != null) {
+ actionsSection.getKeys(false).forEach(order -> {
+ String actionName = npcConfig
+ .getString("actions." + trigger + "." + order + ".action");
+ String value = npcConfig.getString("actions." + trigger + "." + order + ".value");
+ NpcAction action = FancyNpcsPlugin.get().getActionManager().getActionByName(actionName);
+ if (action == null) {
+ BentoBox.getInstance().logWarning("Could not find action: " + actionName);
+ return;
+ }
+
+ try {
+ actionList.add(new NpcAction.NpcActionData(Integer.parseInt(order), action, value));
+ } catch (NumberFormatException e) {
+ BentoBox.getInstance().logWarning("Could not parse order: " + order);
+ }
+ });
+
+ actions.put(actionTrigger, actionList);
+ }
+ });
+ }
+
+ float interactionCooldown = (float) npcConfig.getDouble("interactionCooldown", 0);
+ float scale = (float) npcConfig.getDouble("scale", 1);
+
+ Map attributes = new HashMap<>();
+ if (npcConfig.isConfigurationSection("attributes")) {
+ for (String attrName : npcConfig.getConfigurationSection("attributes").getKeys(false)) {
+ NpcAttribute attribute = FancyNpcsPlugin.get().getAttributeManager().getAttributeByName(type,
+ attrName);
+ if (attribute == null) {
+ BentoBox.getInstance().logWarning("Could not find attribute: " + attrName);
+ continue;
+ }
+
+ String value = npcConfig.getString("attributes." + attrName);
+ if (!attribute.isValidValue(value)) {
+ BentoBox.getInstance().logWarning("Invalid value for attribute: " + attrName);
+ continue;
+ }
+
+ attributes.put(attribute, value);
+ }
+ }
+
+ FancyNpcsPlugin.get().getNpcManager().getNpc(name);
+
+ // When we make a copy, we need to use a new ID
+ String newId = UUID.randomUUID().toString();
+ NpcData data = new NpcData(newId, name, creator, displayName, skin, location, showInTab, spawnEntity,
+ collidable, glowing, glowingColor, type, new HashMap<>(), turnToPlayer, null, actions,
+ interactionCooldown, scale, attributes, mirrorSkin);
+ Npc npc = FancyNpcsPlugin.get().getNpcAdapter().apply(data);
+
+ if (npcConfig.isConfigurationSection("equipment")) {
+ for (String equipmentSlotStr : npcConfig.getConfigurationSection("equipment").getKeys(false)) {
+ NpcEquipmentSlot equipmentSlot = NpcEquipmentSlot.parse(equipmentSlotStr);
+ ItemStack item = npcConfig.getItemStack("equipment." + equipmentSlotStr);
+ npc.getData().addEquipment(equipmentSlot, item);
+ }
+ }
+
+ Bukkit.getScheduler().runTask(getPlugin(), () -> {
+ FancyNpcsPlugin.get().getNpcManager().registerNpc(npc);
+ npc.create();
+ npc.spawnForAll();
+ });
+
+ return true;
+ }
+
+ @Override
+ public boolean hook() {
+ boolean hooked = this.isPluginAvailable();
+ if (!hooked) {
+ BentoBox.getInstance().logError("Could not hook into FancyNpcs");
+ }
+ return hooked; // The hook process shouldn't fail
+ }
+
+ @Override
+ public String getFailureCause() {
+ return null; // The hook process shouldn't fail
+ }
+
+ public Map extends Vector, ? extends List> getNpcsInArea(World world, List vectorsToCopy,
+ @Nullable Vector origin) {
+ Map> bpEntities = new HashMap<>();
+ for (Npc npc : FancyNpcsPlugin.get().getNpcManager().getAllNpcs()) {
+ Location npcLocation = npc.getData().getLocation();
+ Vector spot = new Vector(npcLocation.getBlockX(), npcLocation.getBlockY(), npcLocation.getBlockZ());
+ if (npcLocation.getWorld().equals(world) && vectorsToCopy.contains(spot)) {
+ BlueprintEntity cit = new BlueprintEntity();
+ cit.setType(npc.getData().getType());
+ cit.setNpc(this.serializeNPC(npc, origin));
+ // Retrieve or create the list, then add the entity
+ List entities = bpEntities.getOrDefault(spot, new ArrayList<>());
+ entities.add(cit);
+ // Create position
+ Vector origin2 = origin == null ? new Vector(0, 0, 0) : origin;
+ int x = spot.getBlockX() - origin2.getBlockX();
+ int y = spot.getBlockY() - origin2.getBlockY();
+ int z = spot.getBlockZ() - origin2.getBlockZ();
+ Vector pos = new Vector(x, y, z);
+ // Store
+ bpEntities.put(pos, entities); // Update the map
+ }
+ }
+ return bpEntities;
+ }
+}
diff --git a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java
index 681fd69e7..53c25b4ba 100644
--- a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java
+++ b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java
@@ -940,7 +940,6 @@ public boolean renameHomeLocation(@NonNull Island island, @NonNull String oldNam
*/
@NonNull
public Map getHomeLocations(@NonNull Island island) {
- island.getHomes().forEach((n, l) -> BentoBox.getInstance().logDebug(n));
return island.getHomes();
}
diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java
index c22ba05fe..86ee2e070 100644
--- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java
+++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java
@@ -21,6 +21,7 @@
import org.bukkit.block.data.type.WallSign;
import org.bukkit.block.sign.Side;
import org.bukkit.block.sign.SignSide;
+import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
@@ -33,7 +34,7 @@
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
import world.bentobox.bentobox.database.objects.Island;
-import world.bentobox.bentobox.hooks.CitizensHook;
+import world.bentobox.bentobox.hooks.FancyNpcsHook;
import world.bentobox.bentobox.hooks.MythicMobsHook;
import world.bentobox.bentobox.nms.PasteHandler;
@@ -173,8 +174,6 @@ public static void setSpawner(CreatureSpawner spawner, BlueprintCreatureSpawner
* @return future boolean - true if Bukkit entity spawned, false another plugin entity spawned
*/
public static CompletableFuture setEntity(Island island, Location location, List list) {
- BentoBox.getInstance().logDebug("List of entities to paste at " + location);
- list.forEach(bpe -> BentoBox.getInstance().logDebug(bpe));
World world = location.getWorld();
assert world != null;
return Util.getChunkAtAsync(location).thenRun(() -> list.stream().filter(k -> k.getType() != null)
@@ -184,21 +183,25 @@ public static CompletableFuture setEntity(Island island, Location location
/**
* Spawn an entity
* @param k the blueprint entity definition
- * @param location location
+ * @param location location to paste the entity
* @param island island
* @return true if Bukkit entity spawned, false another plugin entity spawned
*/
static boolean spawnBlueprintEntity(BlueprintEntity k, Location location, Island island) {
- BentoBox.getInstance().logDebug("pasting entity " + k.getType() + " at " + location);
- // Citizens entity
- if (k.getCitizen() != null && plugin.getHooks().getHook("Citizens").filter(mmh -> mmh instanceof CitizensHook)
- .map(mmh -> ((CitizensHook) mmh).spawnCitizen(k.getType(), k.getCitizen(), location)).orElse(false)) {
- BentoBox.getInstance().logDebug("Citizen spawning done");
- // Citizen has spawned.
+ // Npc entity
+ if (k.getNpc() != null
+ && plugin.getHooks().getHook("FancyNpcs").filter(mmh -> mmh instanceof FancyNpcsHook).map(mmh -> {
+ try {
+ return ((FancyNpcsHook) mmh).spawnNpc(k.getNpc(), location);
+ } catch (InvalidConfigurationException e) {
+ plugin.logError("FancyNpc loading failed in blueprint.");
+ return false;
+ }
+ }).orElse(false)) {
+ // Npc has spawned.
return false;
- } else {
- BentoBox.getInstance().logDebug("Citizen spawning failed");
}
+
// Mythic Mobs entity
if (k.getMythicMobsRecord() != null && plugin.getHooks().getHook("MythicMobs")
.filter(mmh -> mmh instanceof MythicMobsHook)
From c6cd8f3cd3442eb0f2b015fd11ede55f0a58503c Mon Sep 17 00:00:00 2001
From: tastybento
Date: Mon, 16 Dec 2024 20:47:43 -0800
Subject: [PATCH 06/10] Bonus range was not being used in the range
Relates to https://github.com/BentoBoxWorld/Upgrades/issues/59
---
pom.xml | 2 +-
.../bentobox/database/objects/Island.java | 12 +-
.../bentobox/database/objects/IslandTest.java | 329 ++++++++++++++++++
3 files changed, 336 insertions(+), 7 deletions(-)
diff --git a/pom.xml b/pom.xml
index c8ed60cb8..ffb166b74 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
-LOCAL
- 3.1.0
+ 3.1.1
bentobox-world
https://sonarcloud.io
${project.basedir}/lib
diff --git a/src/main/java/world/bentobox/bentobox/database/objects/Island.java b/src/main/java/world/bentobox/bentobox/database/objects/Island.java
index 663c31cf0..317a5fbc6 100644
--- a/src/main/java/world/bentobox/bentobox/database/objects/Island.java
+++ b/src/main/java/world/bentobox/bentobox/database/objects/Island.java
@@ -477,7 +477,7 @@ public ImmutableSet getMemberSet() {
* @return the minProtectedX
*/
public int getMinProtectedX() {
- return Math.max(getMinX(), getProtectionCenter().getBlockX() - protectionRange);
+ return Math.max(getMinX(), getProtectionCenter().getBlockX() - this.getProtectionRange());
}
/**
@@ -488,7 +488,7 @@ public int getMinProtectedX() {
* @since 1.5.2
*/
public int getMaxProtectedX() {
- return Math.min(getMaxX(), getProtectionCenter().getBlockX() + protectionRange);
+ return Math.min(getMaxX(), getProtectionCenter().getBlockX() + this.getProtectionRange());
}
/**
@@ -498,7 +498,7 @@ public int getMaxProtectedX() {
* @return the minProtectedZ
*/
public int getMinProtectedZ() {
- return Math.max(getMinZ(), getProtectionCenter().getBlockZ() - protectionRange);
+ return Math.max(getMinZ(), getProtectionCenter().getBlockZ() - this.getProtectionRange());
}
/**
@@ -509,7 +509,7 @@ public int getMinProtectedZ() {
* @since 1.5.2
*/
public int getMaxProtectedZ() {
- return Math.min(getMaxZ(), getProtectionCenter().getBlockZ() + protectionRange);
+ return Math.min(getMaxZ(), getProtectionCenter().getBlockZ() + this.getProtectionRange());
}
/**
@@ -957,9 +957,9 @@ public boolean onIsland(@NonNull Location target) {
|| this.getPlugin().getIWM().isIslandNether(target.getWorld())
|| this.getPlugin().getIWM().isIslandEnd(target.getWorld()))
&& target.getBlockX() >= this.getMinProtectedX()
- && target.getBlockX() < (this.getMinProtectedX() + this.protectionRange * 2)
+ && target.getBlockX() < (this.getMinProtectedX() + this.getProtectionRange() * 2)
&& target.getBlockZ() >= this.getMinProtectedZ()
- && target.getBlockZ() < (this.getMinProtectedZ() + this.protectionRange * 2);
+ && target.getBlockZ() < (this.getMinProtectedZ() + this.getProtectionRange() * 2);
}
/**
diff --git a/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java b/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java
index b2b149abc..eb0e1abb4 100644
--- a/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java
+++ b/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java
@@ -2,6 +2,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -12,10 +13,14 @@
import static org.mockito.Mockito.when;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
+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 org.bukkit.Bukkit;
@@ -24,6 +29,7 @@
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
+import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull;
import org.junit.Before;
@@ -68,12 +74,22 @@ public class IslandTest {
private BentoBox plugin;
@Mock
private IslandWorldManager iwm;
+
@Mock
private World world;
@Mock
+ private World netherWorld;
+ @Mock
+ private World endWorld;
+ @Mock
private User user;
@Mock
private CommandsManager cm;
+ private String uniqueId1;
+ private String uniqueId2;
+ private Island island1;
+ private Island island2;
+ private Island island3;
@Before
public void setUp() throws Exception {
@@ -95,6 +111,12 @@ public void setUp() throws Exception {
// User
when(user.getUniqueId()).thenReturn(uuid);
+ // Nether and End worlds
+ when(iwm.getNetherWorld(world)).thenReturn(netherWorld);
+ when(iwm.getEndWorld(world)).thenReturn(endWorld);
+ when(netherWorld.getName()).thenReturn("bskyblock_nether");
+ when(endWorld.getName()).thenReturn("bskyblock_end");
+
// Bukkit
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
when(Bukkit.getOnlinePlayers()).thenReturn(Collections.emptyList());
@@ -109,9 +131,316 @@ public void setUp() throws Exception {
// Islands Manager
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
+ // Initialize unique IDs for test objects
+ uniqueId1 = UUID.randomUUID().toString();
+ uniqueId2 = UUID.randomUUID().toString();
+
+ // Create Island instances
+ island1 = new Island();
+ island1.setUniqueId(uniqueId1);
+
+ island2 = new Island();
+ island2.setUniqueId(uniqueId1);
+
+ island3 = new Island();
+ island3.setUniqueId(uniqueId2);
+
i = new Island(new Island(location, uuid, 100));
}
+ /**
+ * Test equals method: two objects with the same uniqueId should be equal.
+ */
+ @Test
+ public void testEquals_SameUniqueId() {
+ assertTrue("island1 should equal island2", island1.equals(island2));
+ }
+
+ /**
+ * Test equals method: objects with different uniqueId should not be equal.
+ */
+ @Test
+ public void testEquals_DifferentUniqueId() {
+ assertFalse("island1 should not equal island3", island1.equals(island3));
+ }
+
+ /**
+ * Test equals method: object compared with itself should be equal.
+ */
+ @Test
+ public void testEquals_SameObject() {
+ assertTrue("island1 should equal itself", island1.equals(island1));
+ }
+
+ /**
+ * Test equals method: object compared with null should return false.
+ */
+ @Test
+ public void testEquals_NullObject() {
+ assertFalse("island1 should not equal null", island1.equals(null));
+ }
+
+ /**
+ * Test equals method: object compared with a different class should return false.
+ */
+ @SuppressWarnings("unlikely-arg-type")
+ @Test
+ public void testEquals_DifferentClass() {
+ assertFalse("island1 should not equal a string", island1.equals("someString"));
+ }
+
+ /**
+ * Test hashCode: two objects with the same uniqueId should have the same hashCode.
+ */
+ @Test
+ public void testHashCode_SameUniqueId() {
+ assertEquals("island1 and island2 should have the same hashCode", island1.hashCode(), island2.hashCode());
+ }
+
+ /**
+ * Test hashCode: objects with different uniqueId should have different hashCode.
+ */
+ @Test
+ public void testHashCode_DifferentUniqueId() {
+ assertNotEquals("island1 and island3 should have different hashCodes", island1.hashCode(), island3.hashCode());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.database.objects.Island#Island()}.
+ */
+ @Test
+ public void testIsland() {
+ Island island = new Island();
+ assertNotNull("Island instance should not be null", island);
+ assertNotNull("Unique ID should be initialized", island.getUniqueId());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.database.objects.Island#getRawProtectionRange()}.
+ */
+ @Test
+ public void testGetRawProtectionRange() {
+ int range = 100;
+ Island island = new Island(location, uuid, range);
+ assertEquals("Raw protection range should match", range, island.getRawProtectionRange());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.database.objects.Island#getNetherWorld()}.
+ */
+ @Test
+ public void testGetNetherWorld() {
+ Island island = new Island(location, uuid, 100);
+ when(plugin.getIWM().isNetherGenerate(world)).thenReturn(true);
+ when(plugin.getIWM().isNetherIslands(world)).thenReturn(true);
+ when(plugin.getIWM().getNetherWorld(world)).thenReturn(netherWorld);
+ assertEquals("Nether world should be returned", netherWorld, island.getNetherWorld());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.database.objects.Island#getEndWorld()}.
+ */
+ @Test
+ public void testGetEndWorld() {
+ Island island = new Island(location, uuid, 100);
+ when(plugin.getIWM().getEndWorld(world)).thenReturn(endWorld);
+ when(plugin.getIWM().isEndGenerate(world)).thenReturn(true);
+ when(plugin.getIWM().isEndIslands(world)).thenReturn(true);
+ assertEquals("End world should be returned", endWorld, island.getEndWorld());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.database.objects.Island#getWorld(org.bukkit.World.Environment)}.
+ */
+ @Test
+ public void testGetWorldEnvironment() {
+ Island island = new Island(location, uuid, 100);
+ when(plugin.getIWM().getEndWorld(world)).thenReturn(endWorld);
+ when(plugin.getIWM().isEndGenerate(world)).thenReturn(true);
+ when(plugin.getIWM().isEndIslands(world)).thenReturn(true);
+ when(plugin.getIWM().isNetherGenerate(world)).thenReturn(true);
+ when(plugin.getIWM().isNetherIslands(world)).thenReturn(true);
+ when(plugin.getIWM().getNetherWorld(world)).thenReturn(netherWorld);
+ assertEquals("Normal world should be returned", world, island.getWorld(Environment.NORMAL));
+ assertEquals("Nether world should be returned", netherWorld, island.getWorld(Environment.NETHER));
+ assertEquals("End world should be returned", endWorld, island.getWorld(Environment.THE_END));
+ }
+
+ /**
+ * Test method for {@link world.bentobox.bentobox.database.objects.Island#getBoundingBox(org.bukkit.World.Environment)}.
+ */
+ @Test
+ public void testGetBoundingBoxEnvironment() {
+ Island island = new Island(location, uuid, 100);
+ int dist = iwm.getIslandDistance(world);
+ BoundingBox expected = new BoundingBox(-dist, world.getMinHeight(), -dist, dist, world.getMaxHeight(), dist);
+ BoundingBox result = island.getBoundingBox(Environment.NORMAL);
+ assertEquals("BoundingBox should match", expected, result);
+ }
+
+ @Test
+ public void testGetProtectionBoundingBoxEnvironment() {
+ Island island = new Island(location, uuid, 100);
+ when(world.getMinHeight()).thenReturn(0);
+ when(world.getMaxHeight()).thenReturn(256);
+ BoundingBox expected = new BoundingBox(-100, world.getMinHeight(), -100, 100, world.getMaxHeight(), 100);
+
+ BoundingBox result = island.getProtectionBoundingBox(Environment.NORMAL);
+ assertEquals("Protection bounding box should match", expected, result);
+ }
+
+ @Test
+ public void testIsNetherIslandEnabled() {
+ Island island = new Island(location, uuid, 100);
+ when(plugin.getIWM().isNetherGenerate(world)).thenReturn(true);
+ when(plugin.getIWM().isNetherIslands(world)).thenReturn(true);
+
+ assertTrue("Nether island should be enabled", island.isNetherIslandEnabled());
+ }
+
+ @Test
+ public void testIsEndIslandEnabled() {
+ Island island = new Island(location, uuid, 100);
+ when(plugin.getIWM().isEndGenerate(world)).thenReturn(true);
+ when(plugin.getIWM().isEndIslands(world)).thenReturn(true);
+
+ assertTrue("End island should be enabled", island.isEndIslandEnabled());
+ }
+
+ @Test
+ public void testClearChanged() {
+ Island island = new Island(location, uuid, 100);
+ island.setChanged();
+ assertTrue("Island should be marked as changed", island.isChanged());
+
+ island.clearChanged();
+ assertFalse("Island should not be marked as changed", island.isChanged());
+ }
+
+ @Test
+ public void testRemoveHomes() {
+ Island island = new Island(location, uuid, 100);
+ island.addHome("home1", location);
+ island.addHome("home2", location);
+ assertEquals("Island should have two homes", 2, island.getHomes().size());
+
+ island.removeHomes();
+ assertEquals("Only the default home should remain", 0, island.getHomes().size());
+ }
+
+ @Test
+ public void testGetBonusRanges() {
+ Island island = new Island(location, uuid, 100);
+ assertNotNull("Bonus ranges should not be null", island.getBonusRanges());
+ assertTrue("Bonus ranges should initially be empty", island.getBonusRanges().isEmpty());
+ }
+
+ @Test
+ public void testSetBonusRanges() {
+ Island island = new Island(location, uuid, 100);
+ List bonusRanges = Arrays.asList(new BonusRangeRecord("id1", 10, "Bonus 1"),
+ new BonusRangeRecord("id2", 20, "Bonus 2"));
+ island.setBonusRanges(bonusRanges);
+ assertEquals("Bonus ranges should match", bonusRanges, island.getBonusRanges());
+ assertEquals("Protection range should match", 100 + 10 + 20, island.getProtectionRange());
+ }
+
+ @Test
+ public void testGetBonusRange() {
+ Island island = new Island(location, uuid, 100);
+ island.addBonusRange("id1", 10, "Bonus 1");
+ assertEquals("Bonus range should match", 10, island.getBonusRange("id1"));
+ }
+
+ @Test
+ public void testGetBonusRangeRecord() {
+ Island island = new Island(location, uuid, 100);
+ island.addBonusRange("id1", 10, "Bonus 1");
+ Optional record = island.getBonusRangeRecord("id1");
+ assertTrue("Bonus range record should exist", record.isPresent());
+ assertEquals("Bonus range ID should match", "id1", record.get().getUniqueId());
+ }
+
+ @Test
+ public void testAddBonusRange() {
+ Island island = new Island(location, uuid, 100);
+ island.addBonusRange("id1", 10, "Bonus 1");
+ assertEquals("Bonus range should match", 10, island.getBonusRange("id1"));
+ assertEquals("Protection range should match", 100 + 10, island.getProtectionRange());
+ }
+
+ @Test
+ public void testClearBonusRange() {
+ Island island = new Island(location, uuid, 100);
+ island.addBonusRange("id1", 10, "Bonus 1");
+ island.clearBonusRange("id1");
+ assertEquals("Bonus range should be cleared", 0, island.getBonusRange("id1"));
+ assertEquals("Protection range should match", 100, island.getProtectionRange());
+ }
+
+ @Test
+ public void testClearAllBonusRanges() {
+ Island island = new Island(location, uuid, 100);
+ island.addBonusRange("id1", 10, "Bonus 1");
+ island.addBonusRange("id2", 20, "Bonus 2");
+ assertEquals("Protection range should match", 100 + 10 + 20, island.getProtectionRange());
+ island.clearAllBonusRanges();
+ assertTrue("All bonus ranges should be cleared", island.getBonusRanges().isEmpty());
+ assertEquals("Protection range should match", 100, island.getProtectionRange());
+ }
+
+ @Test
+ public void testIsPrimary() {
+ Island island = new Island(location, uuid, 100);
+ island.setPrimary(uuid);
+ assertTrue("User should be primary", island.isPrimary(uuid));
+ }
+
+ @Test
+ public void testSetPrimary() {
+ Island island = new Island(location, uuid, 100);
+ island.setPrimary(uuid);
+ assertTrue("User should be primary", island.isPrimary(uuid));
+ }
+
+ @Test
+ public void testRemovePrimary() {
+ Island island = new Island(location, uuid, 100);
+ island.setPrimary(uuid);
+ island.removePrimary(uuid);
+ assertFalse("User should not be primary", island.isPrimary(uuid));
+ }
+
+ @Test
+ public void testInTeam() {
+ Island island = new Island(location, uuid, 100);
+ island.addMember(uuid);
+ assertTrue("User should be in team", island.inTeam(uuid));
+ }
+
+ @Test
+ public void testHasTeam() {
+ Island island = new Island(location, uuid, 100);
+ assertFalse("Island should not have a team initially", island.hasTeam());
+ island.addMember(UUID.randomUUID());
+ assertTrue("Island should have a team", island.hasTeam());
+ }
+
+ @Test
+ public void testGetPrimaries() {
+ Island island = new Island(location, uuid, 100);
+ island.setPrimary(uuid);
+ assertTrue("Primaries should contain user", island.getPrimaries().contains(uuid));
+ }
+
+ @Test
+ public void testSetPrimaries() {
+ Island island = new Island(location, uuid, 100);
+ Set primaries = new HashSet<>(Collections.singletonList(uuid));
+ island.setPrimaries(primaries);
+ assertEquals("Primaries should match", primaries, island.getPrimaries());
+ }
+
/**
* Test method for {@link world.bentobox.bentobox.database.objects.Island#Island(org.bukkit.Location, java.util.UUID, int)}.
*/
From 59eabf38d42e4ee858220a65824f756ee1ff0e09 Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 21 Dec 2024 11:06:45 -0800
Subject: [PATCH 07/10] Change to use Mojang by default for head getting
---
src/main/resources/config.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 84e8787f6..20e8b492e 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -93,7 +93,7 @@ panel:
# Mojang API sometime may be slow and may limit requests to the player data, so this will allow to
# get player heads a bit faster then Mojang API.
# Added since 1.16.0.
- use-cache-server: true
+ use-cache-server: false
# Defines how long player skin texture link is stored into local cache before it is requested again.
# Defined value is in the minutes.
# Value 0 will not clear cache until server restart.
From 033d0fa0c28587283ef41d7f95293f91e4357e52 Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 21 Dec 2024 11:43:20 -0800
Subject: [PATCH 08/10] Create modrinth-publish.yml
---
.github/workflows/modrinth-publish.yml | 45 ++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 .github/workflows/modrinth-publish.yml
diff --git a/.github/workflows/modrinth-publish.yml b/.github/workflows/modrinth-publish.yml
new file mode 100644
index 000000000..6eb85e70b
--- /dev/null
+++ b/.github/workflows/modrinth-publish.yml
@@ -0,0 +1,45 @@
+name: Publish
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ publish:
+ name: Publish
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # !!! Make sure to select the correct Java version for your project !!!
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: 21
+ distribution: adopt
+ cache: maven
+
+ # This step will take the version tag from the release and replace it in `pom.xml` before building.
+ - name: Set version from release tag
+ run: mvn -B versions:set -DnewVersion=${{ github.event.release.tag_name }} -DgenerateBackupPoms=false
+
+ - name: Build and package with Maven
+ run: mvn -B clean package --file pom.xml
+
+ - name: Upload to Modrinth
+ uses: cloudnode-pro/modrinth-publish@2.0.0
+ with:
+ # Configure the action as needed. The following is an example.
+ token: ${{ secrets.MODRINTH_TOKEN }}
+ project: aBVLHiAW
+ name: ${{ github.event.release.name }}
+ version: ${{ github.event.release.tag_name }}
+ changelog: ${{ github.event.release.body }}
+ loaders: |-
+ paper
+ spigot
+ game-versions: |-
+ 1.21.3
+ 1.21.4
+ files: target/YourProject-${{ github.event.release.tag_name }}.jar
From 3ac7b288720260c759fcc914442ed1cba90e12be Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 21 Dec 2024 11:47:31 -0800
Subject: [PATCH 09/10] Update modrinth-publish.yml
---
.github/workflows/modrinth-publish.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/modrinth-publish.yml b/.github/workflows/modrinth-publish.yml
index 6eb85e70b..712af3064 100644
--- a/.github/workflows/modrinth-publish.yml
+++ b/.github/workflows/modrinth-publish.yml
@@ -30,7 +30,8 @@ jobs:
- name: Upload to Modrinth
uses: cloudnode-pro/modrinth-publish@2.0.0
with:
- # Configure the action as needed. The following is an example.
+ # Configure the action
+ api-domain: staging-api.modrinth.com
token: ${{ secrets.MODRINTH_TOKEN }}
project: aBVLHiAW
name: ${{ github.event.release.name }}
@@ -42,4 +43,4 @@ jobs:
game-versions: |-
1.21.3
1.21.4
- files: target/YourProject-${{ github.event.release.tag_name }}.jar
+ files: target/BentoBox-${{ github.event.release.tag_name }}.jar
From fc84c7e824beecccd68b9ec8fd621b11269ea27a Mon Sep 17 00:00:00 2001
From: tastybento
Date: Sat, 21 Dec 2024 11:47:58 -0800
Subject: [PATCH 10/10] Update modrinth-publish.yml
---
.github/workflows/modrinth-publish.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/modrinth-publish.yml b/.github/workflows/modrinth-publish.yml
index 712af3064..8244fe239 100644
--- a/.github/workflows/modrinth-publish.yml
+++ b/.github/workflows/modrinth-publish.yml
@@ -31,7 +31,7 @@ jobs:
uses: cloudnode-pro/modrinth-publish@2.0.0
with:
# Configure the action
- api-domain: staging-api.modrinth.com
+ # api-domain: staging-api.modrinth.com
token: ${{ secrets.MODRINTH_TOKEN }}
project: aBVLHiAW
name: ${{ github.event.release.name }}