v1.3.1: NBT preservation, GUI previews, and global placement toggle
This commit is contained in:
57
oyeOwner/INTEGRATION_GUIDE.md
Normal file
57
oyeOwner/INTEGRATION_GUIDE.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# oyeOwner Integration Guide for AI Assistants
|
||||
|
||||
This document provides concise instructions for integrating the **oyeOwner** API into other Bukkit/Spigot plugins.
|
||||
|
||||
## 1. Dependency Configuration (Maven)
|
||||
Add the `oyeOwner` project as a dependency in your `pom.xml`.
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>party.cybsec</groupId>
|
||||
<artifactId>oyeOwner</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## 2. Plugin Configuration (plugin.yml)
|
||||
Add `oyeOwner` as a dependency to ensure it loads before your plugin.
|
||||
|
||||
```yaml
|
||||
depend: [oyeOwner]
|
||||
```
|
||||
|
||||
## 3. Java API Usage
|
||||
|
||||
### Accessing the API
|
||||
The API is accessible via a static getter in the main class: `party.cybsec.OyeOwner.getAPI()`.
|
||||
|
||||
### Sync Lookup (Blocking)
|
||||
Use this if you are already in an asynchronous task or if a tiny delay is acceptable.
|
||||
```java
|
||||
import org.bukkit.block.Block;
|
||||
import party.cybsec.OyeOwner;
|
||||
|
||||
// Returns String username or null
|
||||
String owner = OyeOwner.getAPI().getBlockOwner(block);
|
||||
```
|
||||
|
||||
### Async Lookup (Non-blocking)
|
||||
Recommended for use on the main thread to avoid lag.
|
||||
```java
|
||||
import org.bukkit.block.Block;
|
||||
import party.cybsec.OyeOwner;
|
||||
|
||||
OyeOwner.getAPI().getBlockOwnerAsync(block).thenAccept(owner -> {
|
||||
if (owner != null) {
|
||||
// Player name found: owner
|
||||
} else {
|
||||
// No ownership data found
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 4. Summary of Capabilities
|
||||
- **Lookback Period**: 60 days.
|
||||
- **Action Tracked**: Block Placement (Action ID 1).
|
||||
- **Core Engine**: Powered by CoreProtect with a reflection-based safe hook.
|
||||
73
oyeOwner/pom.xml
Normal file
73
oyeOwner/pom.xml
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>party.cybsec</groupId>
|
||||
<artifactId>oyeOwner</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>oyeOwner</name>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>playpro</id>
|
||||
<url>https://maven.playpro.com</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.21.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>coreprotect</artifactId>
|
||||
<version>23.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.4.2</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
||||
56
oyeOwner/src/main/java/party/cybsec/CoreProtectHook.java
Normal file
56
oyeOwner/src/main/java/party/cybsec/CoreProtectHook.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package party.cybsec;
|
||||
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class CoreProtectHook {
|
||||
|
||||
private final OyeOwner plugin;
|
||||
|
||||
public CoreProtectHook(OyeOwner plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public CoreProtectAPI getCoreProtect() {
|
||||
Plugin cpPlugin = Bukkit.getPluginManager().getPlugin("CoreProtect");
|
||||
|
||||
// Check that CoreProtect is loaded and enabled
|
||||
if (cpPlugin == null || !cpPlugin.isEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Use reflection to get the API to avoid NoClassDefFoundError at load time
|
||||
try {
|
||||
// Verify it's the right class name
|
||||
if (!cpPlugin.getClass().getName().equals("net.coreprotect.CoreProtect")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method getAPIMethod = cpPlugin.getClass().getMethod("getAPI");
|
||||
Object apiObject = getAPIMethod.invoke(cpPlugin);
|
||||
|
||||
if (apiObject instanceof CoreProtectAPI) {
|
||||
CoreProtectAPI api = (CoreProtectAPI) apiObject;
|
||||
|
||||
// Check that the API is enabled
|
||||
if (!api.isEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check that a compatible version of the API is loaded
|
||||
if (api.APIVersion() < 11) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return api;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("Failed to hook into CoreProtect API via reflection: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
50
oyeOwner/src/main/java/party/cybsec/OyeOwner.java
Normal file
50
oyeOwner/src/main/java/party/cybsec/OyeOwner.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package party.cybsec;
|
||||
|
||||
import party.cybsec.command.WhoCommand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class OyeOwner extends JavaPlugin {
|
||||
|
||||
private static OyeOwner instance;
|
||||
private CoreProtectHook coreProtectHook;
|
||||
private OyeOwnerAPI api;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
Logger logger = getLogger();
|
||||
logger.info("oyeOwner is enabling...");
|
||||
|
||||
this.coreProtectHook = new CoreProtectHook(this);
|
||||
this.api = new OyeOwnerAPI(this);
|
||||
|
||||
if (coreProtectHook.getCoreProtect() == null) {
|
||||
logger.severe("CoreProtect not found or incompatible! Disabling oyeOwner.");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
getCommand("who").setExecutor(new WhoCommand(this));
|
||||
|
||||
logger.info("oyeOwner enabled successfully.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLogger().info("oyeOwner disabled.");
|
||||
}
|
||||
|
||||
public CoreProtectHook getCoreProtectHook() {
|
||||
return coreProtectHook;
|
||||
}
|
||||
|
||||
public OyeOwnerAPI getOyeAPI() {
|
||||
return api;
|
||||
}
|
||||
|
||||
public static OyeOwnerAPI getAPI() {
|
||||
return instance.api;
|
||||
}
|
||||
}
|
||||
59
oyeOwner/src/main/java/party/cybsec/OyeOwnerAPI.java
Normal file
59
oyeOwner/src/main/java/party/cybsec/OyeOwnerAPI.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package party.cybsec;
|
||||
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class OyeOwnerAPI {
|
||||
|
||||
private final OyeOwner plugin;
|
||||
|
||||
public OyeOwnerAPI(OyeOwner plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner (player who placed) of a block.
|
||||
* Searches back 60 days.
|
||||
*
|
||||
* @param block The block to check.
|
||||
* @return The username of the player who placed the block, or null if not
|
||||
* found/error.
|
||||
*/
|
||||
public String getBlockOwner(Block block) {
|
||||
CoreProtectAPI api = plugin.getCoreProtectHook().getCoreProtect();
|
||||
if (api == null || block == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 60 days in seconds
|
||||
int time = 60 * 24 * 60 * 60;
|
||||
|
||||
List<String[]> lookup = api.blockLookup(block, time);
|
||||
if (lookup == null || lookup.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (String[] result : lookup) {
|
||||
CoreProtectAPI.ParseResult parsed = api.parseResult(result);
|
||||
// Action ID 1 is "Placement"
|
||||
if (parsed.getActionId() == 1) {
|
||||
return parsed.getPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner of a block asynchronously.
|
||||
*
|
||||
* @param block The block to check.
|
||||
* @return A CompletableFuture containing the username or null.
|
||||
*/
|
||||
public CompletableFuture<String> getBlockOwnerAsync(Block block) {
|
||||
return CompletableFuture.supplyAsync(() -> getBlockOwner(block));
|
||||
}
|
||||
}
|
||||
47
oyeOwner/src/main/java/party/cybsec/command/WhoCommand.java
Normal file
47
oyeOwner/src/main/java/party/cybsec/command/WhoCommand.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package party.cybsec.command;
|
||||
|
||||
import party.cybsec.OyeOwner;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class WhoCommand implements CommandExecutor {
|
||||
|
||||
private final OyeOwner plugin;
|
||||
|
||||
public WhoCommand(OyeOwner plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "Only players can use this command.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
Block targetBlock = player.getTargetBlockExact(5);
|
||||
|
||||
if (targetBlock == null || targetBlock.getType() == Material.AIR) {
|
||||
player.sendMessage(ChatColor.RED + "You must be looking at a block.");
|
||||
return true;
|
||||
}
|
||||
|
||||
String owner = plugin.getOyeAPI().getBlockOwner(targetBlock);
|
||||
|
||||
if (owner != null) {
|
||||
player.sendMessage(ChatColor.DARK_AQUA + "--- Block Owner Info ---");
|
||||
player.sendMessage(ChatColor.GOLD + "user: " + ChatColor.WHITE + owner);
|
||||
player.sendMessage(ChatColor.DARK_AQUA + "------------------------");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.sendMessage(ChatColor.GRAY + "No placement records found for this block.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
14
oyeOwner/src/main/resources/plugin.yml
Normal file
14
oyeOwner/src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
name: oyeOwner
|
||||
version: '1.0'
|
||||
main: party.cybsec.OyeOwner
|
||||
api-version: '1.21'
|
||||
depend: [CoreProtect]
|
||||
commands:
|
||||
who:
|
||||
description: check who placed the block you are looking at
|
||||
permission: oyeowner.use
|
||||
usage: /<command>
|
||||
permissions:
|
||||
oyeowner.use:
|
||||
description: Allows player to use the /who command
|
||||
default: op
|
||||
BIN
oyeOwner/target/classes/party/cybsec/CoreProtectHook.class
Normal file
BIN
oyeOwner/target/classes/party/cybsec/CoreProtectHook.class
Normal file
Binary file not shown.
BIN
oyeOwner/target/classes/party/cybsec/OyeOwner.class
Normal file
BIN
oyeOwner/target/classes/party/cybsec/OyeOwner.class
Normal file
Binary file not shown.
BIN
oyeOwner/target/classes/party/cybsec/OyeOwnerAPI.class
Normal file
BIN
oyeOwner/target/classes/party/cybsec/OyeOwnerAPI.class
Normal file
Binary file not shown.
BIN
oyeOwner/target/classes/party/cybsec/command/WhoCommand.class
Normal file
BIN
oyeOwner/target/classes/party/cybsec/command/WhoCommand.class
Normal file
Binary file not shown.
14
oyeOwner/target/classes/plugin.yml
Normal file
14
oyeOwner/target/classes/plugin.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
name: oyeOwner
|
||||
version: '1.0'
|
||||
main: party.cybsec.OyeOwner
|
||||
api-version: '1.21'
|
||||
depend: [CoreProtect]
|
||||
commands:
|
||||
who:
|
||||
description: check who placed the block you are looking at
|
||||
permission: oyeowner.use
|
||||
usage: /<command>
|
||||
permissions:
|
||||
oyeowner.use:
|
||||
description: Allows player to use the /who command
|
||||
default: op
|
||||
3
oyeOwner/target/maven-archiver/pom.properties
Normal file
3
oyeOwner/target/maven-archiver/pom.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
artifactId=oyeOwner
|
||||
groupId=party.cybsec
|
||||
version=1.0-SNAPSHOT
|
||||
@@ -0,0 +1,4 @@
|
||||
party/cybsec/command/WhoCommand.class
|
||||
party/cybsec/OyeOwner.class
|
||||
party/cybsec/CoreProtectHook.class
|
||||
party/cybsec/OyeOwnerAPI.class
|
||||
@@ -0,0 +1,4 @@
|
||||
/Users/jacktotonchi/oyeOwner/src/main/java/party/cybsec/CoreProtectHook.java
|
||||
/Users/jacktotonchi/oyeOwner/src/main/java/party/cybsec/OyeOwner.java
|
||||
/Users/jacktotonchi/oyeOwner/src/main/java/party/cybsec/OyeOwnerAPI.java
|
||||
/Users/jacktotonchi/oyeOwner/src/main/java/party/cybsec/command/WhoCommand.java
|
||||
Reference in New Issue
Block a user