v3.0 Release
This commit is contained in:
1 parent
9152e4d385
commit
54e6927103
10 files changed
+292
-148
No files matched your search
+12
-14
@@ -1,18 +1,6 @@
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Eclipse classpath file
|
||||
*.classpath
|
||||
|
||||
# Eclipse project file
|
||||
*.project
|
||||
|
||||
# Eclipse settings
|
||||
*.settings
|
||||
|
||||
# Gradle build output
|
||||
bin/
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
@@ -33,7 +21,17 @@ bin/
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
replay_pid*
|
||||
|
||||
# Gradle post-build folders
|
||||
.gradle
|
||||
# macOS system files
|
||||
.DS_Store
|
||||
|
||||
# gradle build output files
|
||||
build/
|
||||
.gradle/
|
||||
|
||||
# eclipse project files
|
||||
.settings/
|
||||
.project
|
||||
.classpath
|
||||
bin/
|
||||
@@ -14,6 +14,14 @@ To build:
|
||||
|
||||
The resulting .jar file will be in build/libs/
|
||||
|
||||
*Version 3.0 Changelog:*
|
||||
|
||||
- Setting the age now applies to all items.
|
||||
|
||||
- Added more logic for persistence.
|
||||
|
||||
- Added support for human readable time format.
|
||||
|
||||
*Version 2.1 Changelog:*
|
||||
|
||||
- Fixed NBT-API import in gradle.
|
||||
@@ -44,9 +52,9 @@ The resulting .jar file will be in build/libs/
|
||||
|
||||
- Change the amount of time it takes for items to despawn.
|
||||
|
||||
- Set in-game warnings for when items are about to despawn. (Coming in 3.0)
|
||||
- Set in-game warnings for when items are about to despawn. (Coming in 3.1)
|
||||
|
||||
- Clear items with an in-game command. (Coming in 3.0)
|
||||
- Clear items with an in-game command. (Coming in 3.1)
|
||||
|
||||
Uses [NBTAPI](https://github.com/tr7zw/Item-NBT-API).
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
plugins {
|
||||
|
||||
id "java" // Tell gradle this is a java project.
|
||||
id "com.github.johnrengelman.shadow" version "7.1.2" // Import utility to package libraries into .jar file.
|
||||
|
||||
}
|
||||
|
||||
group = "net.trueog.nodespawnog" // Declare package name.
|
||||
version = "2.1" // Declare package version.
|
||||
|
||||
def apiVersion = "1.19.4" // Declare minecraft server target version.
|
||||
def targetJavaVersion = 17 // Declare java compatibility minimum.
|
||||
|
||||
apply plugin: "eclipse" // Enable integration with Eclipse IDE for development.
|
||||
|
||||
processResources {
|
||||
|
||||
def props = [
|
||||
version: version,
|
||||
apiVersion: apiVersion,
|
||||
]
|
||||
|
||||
inputs.properties props // Indicates to rerun if version changes.
|
||||
|
||||
filesMatching("plugin.yml") {
|
||||
|
||||
expand props
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
|
||||
url "https://repo.purpurmc.org/snapshots" // Get purpur API from purpur maven repository.
|
||||
|
||||
}
|
||||
|
||||
maven {
|
||||
|
||||
name = "CodeMC"
|
||||
url = uri("https://repo.codemc.org/repository/maven-public/") // Get NBT-API from codemc maven repository.
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
compileOnly "org.purpurmc.purpur:purpur-api:1.18.2-R0.1-SNAPSHOT" // Declare purpur API version to be packaged.
|
||||
|
||||
implementation("de.tr7zw:item-nbt-api:2.11.1") // Declare NBT-API version to be packaged.
|
||||
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
|
||||
minimize()
|
||||
|
||||
relocate 'de.tr7zw', 'net.trueog.nodespawnog.item-nbt-api' // Prevent conflicts with other NBT-API utilizing plugins.
|
||||
|
||||
}
|
||||
|
||||
jar.dependsOn shadowJar
|
||||
@@ -0,0 +1,93 @@
|
||||
plugins {
|
||||
java // Tell gradle this is a java project.
|
||||
id("io.github.goooler.shadow") version "8.1.8"
|
||||
eclipse // Import eclipse plugin for IDE integration.
|
||||
kotlin("jvm") version "1.9.23" // Import kotlin jvm plugin for kotlin/java integration.
|
||||
}
|
||||
|
||||
java {
|
||||
// Declare java version.
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
group = "net.trueog.nodespawnog" // Declare bundle identifier.
|
||||
version = "3.0" // Declare plugin version (will be in .jar).
|
||||
val apiVersion = "1.19" // Declare minecraft server target version.
|
||||
|
||||
tasks.named<ProcessResources>("processResources") {
|
||||
val props = mapOf(
|
||||
"version" to version,
|
||||
"apiVersion" to apiVersion
|
||||
)
|
||||
|
||||
inputs.properties(props) // Indicates to rerun if version changes.
|
||||
|
||||
filesMatching("plugin.yml") {
|
||||
expand(props)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
url = uri("https://repo.purpurmc.org/snapshots")
|
||||
}
|
||||
|
||||
maven {
|
||||
|
||||
url = uri("https://repo.codemc.org/repository/maven-public/") // Get NBT-API from codemc maven repository.
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare purpur API version to be packaged.
|
||||
compileOnly("io.github.miniplaceholders:miniplaceholders-api:2.2.3") // Import MiniPlaceholders API.
|
||||
implementation("de.tr7zw:item-nbt-api:2.11.1") // Declare NBT-API version to be packaged.
|
||||
}
|
||||
|
||||
tasks.withType<AbstractArchiveTask>().configureEach {
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
|
||||
relocate("de.tr7zw", "net.trueog.nodespawnog.item-nbt-api") // Prevent conflicts with other NBT-API utilizing plugins
|
||||
minimize()
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
dependsOn(tasks.shadowJar)
|
||||
archiveClassifier.set("part")
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
archiveClassifier.set("") // Use empty string instead of null
|
||||
from("LICENSE") {
|
||||
into("/")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
dependsOn("shadowJar")
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.add("-parameters")
|
||||
options.encoding = "UTF-8"
|
||||
options.isFork = true
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
vendor = JvmVendorSpec.GRAAL_VM
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
||||
File renamed without changes.
@@ -1,13 +1,23 @@
|
||||
package net.trueog.nodespawnog;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTEntity;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
|
||||
// Class to watch for in-game events.
|
||||
public class EventListener implements Listener {
|
||||
@@ -18,87 +28,190 @@ public class EventListener implements Listener {
|
||||
// If despawn time is set to this, it never changes.
|
||||
public short minimumValue = -32768;
|
||||
|
||||
// Get the user-set death despawn time value.
|
||||
private short valueOfDespawnTime() {
|
||||
// Determine the despawn time using the number taken from the config file.
|
||||
private short calculateDespawnTime() {
|
||||
|
||||
// Declare an empty short object for holding the death despawn time from the config file after input validation.
|
||||
short valueOfDespawnTime = 0;
|
||||
// Get the user-defined despawn time from the config file.
|
||||
String timeString = config.getString("time-to-death-despawns");
|
||||
|
||||
// Read config for death despawn in such a way as to validate that it would be a valid 'short'.
|
||||
try {
|
||||
// If the config value is empty, do this...
|
||||
if (timeString == null || timeString.isEmpty()) {
|
||||
|
||||
// TODO: Allow for specifying time in seconds, minutes, or hours, instead of ticks.
|
||||
// Get value for time to death despawns from config file.
|
||||
int intOfDespawnTime = config.getInt("time-to-death-despawns");
|
||||
|
||||
// Convert the integer specified by the user to a negative short via a string for data type compliance and error handling.
|
||||
valueOfDespawnTime = Short.valueOf(String.valueOf(-1 * intOfDespawnTime));
|
||||
|
||||
// Set short to valid user-set death despawn time.
|
||||
// This will only run if the short the user specified in the config was in range.
|
||||
return valueOfDespawnTime;
|
||||
// Default to 5 minutes (using ticks).
|
||||
return Short.valueOf(String.valueOf(-1 * 6000));
|
||||
|
||||
}
|
||||
// If the value the user set in the config is out of range, do this.
|
||||
catch(NumberFormatException error) {
|
||||
|
||||
// Return default value of 6000 ticks (5 minutes) to replace invalid user-set value in the config.
|
||||
// Deconstruct and interpret the user-specified time string.
|
||||
try {
|
||||
|
||||
// Declare a variable to hold the time.
|
||||
long time;
|
||||
|
||||
// Extract the unit (s, m, h).
|
||||
String unit = timeString.replaceAll("\\d", "");
|
||||
|
||||
// Extract the numeric value.
|
||||
int value = Integer.parseInt(timeString.replaceAll("\\D", ""));
|
||||
|
||||
switch (unit.toLowerCase()) {
|
||||
case "s":
|
||||
// Convert seconds to ticks.
|
||||
time = value * 20L;
|
||||
break;
|
||||
case "m":
|
||||
// Convert minutes to ticks.
|
||||
time = value * 20L * 60L;
|
||||
break;
|
||||
case "h":
|
||||
// Convert hours to ticks.
|
||||
time = value * 20L * 60L * 60L;
|
||||
break;
|
||||
default:
|
||||
// Default to ticks if no unit is provided.
|
||||
time = value;
|
||||
}
|
||||
|
||||
// Start the countdown to despawn.
|
||||
return Short.valueOf(String.valueOf(-1 * time));
|
||||
|
||||
}
|
||||
// If the user-specified time string is in an invalid format, do this...
|
||||
catch (NumberFormatException error) {
|
||||
|
||||
// Default to 5 minutes (using ticks).
|
||||
return Short.valueOf(String.valueOf(-1 * 6000));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Override entityDeathEvent with the highest possible priority.
|
||||
// Prioritize this event listener over all other plugins.
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void entityDeathEvent(EntityDeathEvent PlayerDeathEvent) {
|
||||
// Runs whenever an entity dies.
|
||||
public void entityDeathEvent(EntityDeathEvent event) {
|
||||
|
||||
// If a player died, do this.
|
||||
if (PlayerDeathEvent.getEntity().getType().equals(org.bukkit.entity.EntityType.PLAYER)) {
|
||||
// Check if the entity is a player.
|
||||
if (! (event.getEntity() instanceof Player)) {
|
||||
|
||||
// If the player's inventory was not empty, do this.
|
||||
if(! PlayerDeathEvent.getDrops().isEmpty()) {
|
||||
// If the entity is not a player, skip this event.
|
||||
return;
|
||||
|
||||
// If disable death despawns option is enabled in config file, do this.
|
||||
if(config.getBoolean("disable-death-despawns") == true) {
|
||||
}
|
||||
|
||||
// For each intended drop item, do this.
|
||||
PlayerDeathEvent.getDrops().forEach(element -> {
|
||||
// If the player's inventory was not empty...
|
||||
if (! event.getDrops().isEmpty()) {
|
||||
|
||||
// Get what the item was.
|
||||
Item droppedItem = PlayerDeathEvent.getEntity().getWorld().dropItem(PlayerDeathEvent.getEntity().getLocation(), element);
|
||||
// Loop through every item in the death pile.
|
||||
event.getDrops().forEach(itemStack -> {
|
||||
|
||||
// Create a new item drop of the same thing using NBT.
|
||||
NBTEntity newDropNBT = new NBTEntity(droppedItem);
|
||||
// Get each item from the dropped entities.
|
||||
Item droppedItem = event.getEntity().getWorld().dropItem(event.getEntity().getLocation(), itemStack);
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
|
||||
// Set items upon death to stay spawned in infinitely
|
||||
newDropNBT.setShort("Age", minimumValue);
|
||||
// Set the Age tag based on the value set in the config file.
|
||||
nbtItem.setShort("Age", config.getBoolean("disable-death-despawns") ? minimumValue : calculateDespawnTime());
|
||||
|
||||
});
|
||||
// Save the modified NBT data.
|
||||
PersistentDataContainer pdc = droppedItem.getPersistentDataContainer();
|
||||
NamespacedKey key = new NamespacedKey(NoDespawnOG.getPlugin(), "nodespawn_age");
|
||||
pdc.set(key, PersistentDataType.INTEGER, (int) nbtItem.getShort("Age"));
|
||||
|
||||
// Delete the original entities to prevent duplication.
|
||||
PlayerDeathEvent.getDrops().clear();
|
||||
// Apply the modified NBTItem back to the ItemStack and update the dropped Item.
|
||||
itemStack = nbtItem.getItem();
|
||||
droppedItem.setItemStack(itemStack);
|
||||
|
||||
});
|
||||
|
||||
// Clear the original drops.
|
||||
event.getDrops().clear();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Runs every time a chunk is loaded.
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
|
||||
// Get the chunk that was loaded.
|
||||
Chunk chunk = event.getChunk();
|
||||
// Loop through every entity in the chunk.
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
|
||||
// If the entity is an Item, do this...
|
||||
if (entity instanceof Item) {
|
||||
|
||||
// Cast the entity to an Item since it is one.
|
||||
Item item = (Item) entity;
|
||||
|
||||
// Declare a container to hold item data.
|
||||
PersistentDataContainer pdc = item.getPersistentDataContainer();
|
||||
NamespacedKey key = new NamespacedKey(NoDespawnOG.getPlugin(), "nodespawn_age");
|
||||
// Check for item age.
|
||||
if (pdc.has(key, PersistentDataType.INTEGER)) {
|
||||
|
||||
// Derive the item age.
|
||||
short savedAge = pdc.get(key, PersistentDataType.INTEGER).shortValue();
|
||||
|
||||
// Get the ItemStack from the Item.
|
||||
ItemStack itemStack = item.getItemStack();
|
||||
|
||||
// Apply the saved age using NBTItem.
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
nbtItem.setShort("Age", savedAge);
|
||||
itemStack = nbtItem.getItem();
|
||||
|
||||
// Update the Item with the modified ItemStack.
|
||||
item.setItemStack(itemStack);
|
||||
|
||||
}
|
||||
// If disable death despawns is disabled in the config file, do this.
|
||||
else {
|
||||
|
||||
// For each intended drop item, do this.
|
||||
PlayerDeathEvent.getDrops().forEach(element -> {
|
||||
}
|
||||
|
||||
// Get what the item was.
|
||||
Item droppedItem = PlayerDeathEvent.getEntity().getWorld().dropItem(PlayerDeathEvent.getEntity().getLocation(), element);
|
||||
}
|
||||
|
||||
// Create a new item drop of the same thing using NBT.
|
||||
NBTEntity newDropNBT = new NBTEntity(droppedItem);
|
||||
}
|
||||
|
||||
// Set items upon death to stay spawned in for the calculated amount of time.
|
||||
newDropNBT.setShort("Age", valueOfDespawnTime());
|
||||
// Runs every time a world is loaded.
|
||||
@EventHandler
|
||||
public void onWorldLoad(WorldLoadEvent event) {
|
||||
|
||||
});
|
||||
// Get the world that was loaded.
|
||||
World world = event.getWorld();
|
||||
// Loop through all loaded chunks in the world.
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
|
||||
// Delete the original entities to prevent duplication.
|
||||
PlayerDeathEvent.getDrops().clear();
|
||||
// Loop through every entity in the chunk.
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
|
||||
// If the entity is an Item, do this...
|
||||
if (entity instanceof Item) {
|
||||
|
||||
// Cast the entity to an Item since it is one.
|
||||
Item item = (Item) entity;
|
||||
|
||||
// Declare a container to hold item data.
|
||||
PersistentDataContainer pdc = item.getPersistentDataContainer();
|
||||
NamespacedKey key = new NamespacedKey(NoDespawnOG.getPlugin(), "nodespawn_age");
|
||||
// Check for item age.
|
||||
if (pdc.has(key, PersistentDataType.INTEGER)) {
|
||||
|
||||
// Derive the item age.
|
||||
short savedAge = pdc.get(key, PersistentDataType.INTEGER).shortValue();
|
||||
|
||||
// Get the ItemStack from the Item.
|
||||
ItemStack itemStack = item.getItemStack();
|
||||
|
||||
// Apply the saved age using NBTItem.
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
nbtItem.setShort("Age", savedAge);
|
||||
itemStack = nbtItem.getItem();
|
||||
|
||||
// Update the Item with the modified ItemStack.
|
||||
item.setItemStack(itemStack);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public class NoDespawnOG extends JavaPlugin {
|
||||
saveDefaultConfig();
|
||||
|
||||
// Log valid plugin launch to console.
|
||||
getLogger().info("NoDespawn 2.1 Loaded.");
|
||||
getLogger().info("NoDespawn 2.2 Loaded.");
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class NoDespawnOG extends JavaPlugin {
|
||||
@Override public void onDisable() {
|
||||
|
||||
// Log valid plugin shut-down to console.
|
||||
getLogger().info("NoDespawn 2.1 Shut Down without errors.");
|
||||
getLogger().info("NoDespawn 2.2 Shut Down without errors.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# NoDespawn-OG 2.1 Config.
|
||||
# NoDespawn-OG 3.0 Config.
|
||||
|
||||
# Should item despawning be completely disabled on player death?
|
||||
disable-death-despawns: true
|
||||
|
||||
# How long should all other entities take to despawn? (in ticks).
|
||||
# How long should all other entities take to despawn? (in ticks, seconds (s), minutes (m), or hours (h))
|
||||
# The vanilla behavior is 300 seconds, or 5 Minutes (roughly 6000 ticks).
|
||||
# This will not impact non-death-pile entities until 3.0.
|
||||
time-to-despawn: 6000
|
||||
# If the format of this option is invalid, NoDespawn-OG will default to 5 minutes.
|
||||
time-to-despawn: 5m
|
||||
|
||||
# If disable despawns is set to false, how long (in ticks) should items dropped on death last until despawn?
|
||||
# Values range from 0 (instant despawn) to 32767 ticks (roughly 27 minutes).
|
||||
# If disable despawns is set to false, how long (in ticks, seconds (s), minutes (m), or hours (h))
|
||||
# should items dropped on death last until despawn?
|
||||
# If higher than the max or lower than the min, defaults to the value of time-to-despawn above.
|
||||
time-to-death-despawns: 12000
|
||||
time-to-death-despawns: 20m
|
||||
@@ -3,5 +3,5 @@ name: NoDespawn-OG
|
||||
authors: [BadPylot, NotAlexNoyle]
|
||||
description: A Spigot plugin that allows you to easily determine when exactly you or others first joined the server!
|
||||
website: https://github.com/NotAlexNoyle/NoDespawn-OG
|
||||
version: 2.1
|
||||
api-version: 1.19
|
||||
version: '${version}'
|
||||
api-version: 1.19
|
||||
Reference in new issue
Block a user