mirror of
https://github.com/KoopaCode/UltraStack.git
synced 2025-04-02 22:47:32 +00:00
0.0.1-ALPHA
This commit is contained in:
parent
dc1d429288
commit
7734a9b407
90
.github/workflows/build.yml
vendored
Normal file
90
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
name: Build
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
cache: maven
|
||||
|
||||
- name: Get Project Info
|
||||
run: |
|
||||
echo "PLUGIN_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||
echo "PLUGIN_NAME=$(mvn help:evaluate -Dexpression=project.name -q -DforceStdout)" >> $GITHUB_ENV
|
||||
echo "PLUGIN_FILE=$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout)" >> $GITHUB_ENV
|
||||
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
|
||||
- name: Debug Directory
|
||||
run: ls -la target/
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.PLUGIN_FILE }}-${{ env.PLUGIN_VERSION }}
|
||||
path: target/${{ env.PLUGIN_FILE }}-${{ env.PLUGIN_VERSION }}.jar
|
||||
retention-days: 30
|
||||
|
||||
- name: Send Build Notification
|
||||
if: always()
|
||||
uses: sarisia/actions-status-discord@v1
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
title: "${{ job.status == 'success' && '✅ Build Success!' || '❌ Build Failed!' }}"
|
||||
description: |
|
||||
**${{ env.PLUGIN_NAME }} v${{ env.PLUGIN_VERSION }}**
|
||||
By ${{ github.actor }} • ${{ github.sha }}
|
||||
${{ github.repository }}
|
||||
color: ${{ job.status == 'success' && '0x00ff00' || '0xff0000' }}
|
||||
username: "🏺Artifact Build's"
|
||||
avatar_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
|
||||
release:
|
||||
needs: build
|
||||
if: github.event_name == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ env.PLUGIN_FILE }}-${{ env.PLUGIN_VERSION }}
|
||||
|
||||
- name: Upload Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ${{ env.PLUGIN_FILE }}-${{ env.PLUGIN_VERSION }}.jar
|
||||
fail_on_unmatched_files: true
|
||||
|
||||
- name: Send Release Notification
|
||||
if: always()
|
||||
uses: sarisia/actions-status-discord@v1
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
title: "${{ job.status == 'success' && '🎉 Release Published!' || '❌ Release Failed!' }}"
|
||||
description: |
|
||||
**${{ env.PLUGIN_NAME }} v${{ env.PLUGIN_VERSION }}**
|
||||
${{ job.status == 'success' && '➜ https://github.com/${{ github.repository }}/releases/latest' || '' }}
|
||||
color: ${{ job.status == 'success' && '0x00ff00' || '0xff0000' }}
|
||||
username: "🏺Artifact Build's"
|
||||
avatar_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
28
.gitignore
vendored
28
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
# Maven
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
@ -10,8 +11,29 @@ buildNumber.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
# Eclipse m2e generated files
|
||||
# Eclipse Core
|
||||
# IDE files
|
||||
.idea/
|
||||
*.iml
|
||||
.settings/
|
||||
.project
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
.vscode/
|
||||
|
||||
# Compiled files
|
||||
*.class
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# OS generated files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
74
pom.xml
Normal file
74
pom.xml
Normal file
@ -0,0 +1,74 @@
|
||||
<?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>com.koopalabs</groupId>
|
||||
<artifactId>ultrastack</artifactId>
|
||||
<version>0.0.1-ALPHA</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>UltraStack</name>
|
||||
<description>Configurable item stacking plugin with multi-world support</description>
|
||||
<url>discord.gg/KmHGjaHWct</url>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<!-- Spigot-API -->
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spigot-API -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.21.4-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
164
src/main/java/com/koopalabs/ultrastack/StackListener.java
Normal file
164
src/main/java/com/koopalabs/ultrastack/StackListener.java
Normal file
@ -0,0 +1,164 @@
|
||||
package com.koopalabs.ultrastack;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Entity;
|
||||
import java.util.List;
|
||||
|
||||
public class StackListener implements Listener {
|
||||
private final UltraStack plugin;
|
||||
|
||||
public StackListener(UltraStack plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onItemSpawn(ItemSpawnEvent event) {
|
||||
if (!plugin.getConfig().getBoolean("performance.update-on-spawn")) return;
|
||||
if (!plugin.isWorldEnabled(event.getLocation().getWorld())) return;
|
||||
|
||||
Item newItem = event.getEntity();
|
||||
ItemStack stack = newItem.getItemStack();
|
||||
if (stack == null || stack.getType() == Material.AIR) return;
|
||||
|
||||
int maxStack = plugin.getMaxStackSize(stack.getType());
|
||||
|
||||
// Get all nearby items first
|
||||
List<Item> nearbyItems = new java.util.ArrayList<>();
|
||||
for (Entity entity : newItem.getNearbyEntities(2, 2, 2)) {
|
||||
if (entity instanceof Item && entity != newItem) {
|
||||
Item item = (Item) entity;
|
||||
if (item.getItemStack().isSimilar(stack)) {
|
||||
nearbyItems.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we found similar items, merge them all
|
||||
if (!nearbyItems.isEmpty()) {
|
||||
int totalAmount = stack.getAmount();
|
||||
for (Item item : nearbyItems) {
|
||||
totalAmount += item.getItemStack().getAmount();
|
||||
item.remove(); // Remove the old items
|
||||
}
|
||||
|
||||
// Create a new stack with the total amount
|
||||
if (totalAmount > maxStack) {
|
||||
// If total exceeds max, create minimum number of full stacks
|
||||
while (totalAmount > maxStack) {
|
||||
ItemStack newStack = stack.clone();
|
||||
newStack.setAmount(maxStack);
|
||||
newItem.getWorld().dropItem(newItem.getLocation(), newStack);
|
||||
totalAmount -= maxStack;
|
||||
}
|
||||
|
||||
// Drop remaining items if any
|
||||
if (totalAmount > 0) {
|
||||
stack.setAmount(totalAmount);
|
||||
newItem.setItemStack(stack);
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} else {
|
||||
// If total is within max, just set the amount
|
||||
stack.setAmount(totalAmount);
|
||||
newItem.setItemStack(stack);
|
||||
}
|
||||
} else {
|
||||
// No nearby items, just ensure proper stack size
|
||||
if (stack.getAmount() > maxStack) {
|
||||
int amount = stack.getAmount();
|
||||
stack.setAmount(maxStack);
|
||||
|
||||
// Create additional stacks if needed
|
||||
amount -= maxStack;
|
||||
while (amount > 0) {
|
||||
int nextAmount = Math.min(amount, maxStack);
|
||||
ItemStack nextStack = stack.clone();
|
||||
nextStack.setAmount(nextAmount);
|
||||
newItem.getWorld().dropItem(newItem.getLocation(), nextStack);
|
||||
amount -= nextAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!plugin.getConfig().getBoolean("performance.update-on-inventory-click")) return;
|
||||
if (!plugin.isWorldEnabled(event.getWhoClicked().getWorld())) return;
|
||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||
|
||||
ItemStack current = event.getCurrentItem();
|
||||
ItemStack cursor = event.getCursor();
|
||||
|
||||
// Only handle clicks with items
|
||||
if (current == null || current.getType() == Material.AIR) return;
|
||||
|
||||
int maxStack = plugin.getMaxStackSize(current.getType());
|
||||
if (maxStack <= current.getType().getMaxStackSize()) return;
|
||||
|
||||
// Handle merging items
|
||||
if (cursor != null && cursor.getType() != Material.AIR &&
|
||||
cursor.isSimilar(current) &&
|
||||
event.getAction() == InventoryAction.PLACE_ALL) {
|
||||
|
||||
int totalAmount = cursor.getAmount() + current.getAmount();
|
||||
if (totalAmount <= maxStack) {
|
||||
event.setCancelled(true);
|
||||
current.setAmount(totalAmount);
|
||||
cursor.setAmount(0);
|
||||
} else if (current.getAmount() < maxStack) {
|
||||
event.setCancelled(true);
|
||||
current.setAmount(maxStack);
|
||||
cursor.setAmount(totalAmount - maxStack);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure stack size doesn't exceed our max
|
||||
if (current.getAmount() > maxStack) {
|
||||
current.setAmount(maxStack);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onEntityPickupItem(EntityPickupItemEvent event) {
|
||||
if (!plugin.getConfig().getBoolean("performance.update-on-pickup")) return;
|
||||
if (!plugin.isWorldEnabled(event.getEntity().getWorld())) return;
|
||||
if (!(event.getEntity() instanceof Player)) return;
|
||||
|
||||
Player player = (Player) event.getEntity();
|
||||
ItemStack pickupItem = event.getItem().getItemStack();
|
||||
if (pickupItem == null || pickupItem.getType() == Material.AIR) return;
|
||||
|
||||
int maxStack = plugin.getMaxStackSize(pickupItem.getType());
|
||||
if (maxStack <= pickupItem.getType().getMaxStackSize()) return;
|
||||
|
||||
// Try to merge with existing stacks first
|
||||
PlayerInventory inv = player.getInventory();
|
||||
for (ItemStack invItem : inv.getStorageContents()) {
|
||||
if (invItem != null && invItem.isSimilar(pickupItem) && invItem.getAmount() < maxStack) {
|
||||
int space = maxStack - invItem.getAmount();
|
||||
if (pickupItem.getAmount() <= space) {
|
||||
invItem.setAmount(invItem.getAmount() + pickupItem.getAmount());
|
||||
event.getItem().remove();
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't merge, just ensure the stack size is valid
|
||||
pickupItem.setAmount(Math.min(maxStack, pickupItem.getAmount()));
|
||||
}
|
||||
}
|
61
src/main/java/com/koopalabs/ultrastack/UltraStack.java
Normal file
61
src/main/java/com/koopalabs/ultrastack/UltraStack.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.koopalabs.ultrastack;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class UltraStack extends JavaPlugin implements Listener {
|
||||
private static UltraStack instance;
|
||||
private FileConfiguration config;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
saveDefaultConfig();
|
||||
loadConfig();
|
||||
|
||||
// Register events
|
||||
getServer().getPluginManager().registerEvents(new StackListener(this), this);
|
||||
|
||||
// Register commands
|
||||
getCommand("ultrastack").setExecutor(new UltraStackCommand(this));
|
||||
}
|
||||
|
||||
public void loadConfig() {
|
||||
reloadConfig();
|
||||
config = getConfig();
|
||||
}
|
||||
|
||||
public boolean isWorldEnabled(World world) {
|
||||
if (!config.getBoolean("enabled")) return false;
|
||||
|
||||
if (config.getStringList("worlds.disabled-worlds").contains(world.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
java.util.List<String> enabledWorlds = config.getStringList("worlds.enabled-worlds");
|
||||
return enabledWorlds.contains("all") || enabledWorlds.contains(world.getName());
|
||||
}
|
||||
|
||||
public int getMaxStackSize(Material material) {
|
||||
String mode = config.getString("stack-settings.mode", "all");
|
||||
|
||||
if (mode.equalsIgnoreCase("all")) {
|
||||
return config.getInt("stack-settings.default-stack-size", 64000);
|
||||
}
|
||||
|
||||
String path = "stack-settings.items." + material.name();
|
||||
if (config.contains(path) && config.getBoolean(path + ".enabled")) {
|
||||
return config.getInt(path + ".max-stack", 64);
|
||||
}
|
||||
|
||||
return material.getMaxStackSize();
|
||||
}
|
||||
|
||||
public static UltraStack getInstance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.koopalabs.ultrastack;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class UltraStackCommand implements CommandExecutor {
|
||||
private final UltraStack plugin;
|
||||
|
||||
public UltraStackCommand(UltraStack plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!sender.hasPermission("ultrastack.admin")) {
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&',
|
||||
plugin.getConfig().getString("messages.prefix") + " " +
|
||||
plugin.getConfig().getString("messages.no-permission")));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length > 0 && args[0].equalsIgnoreCase("reload")) {
|
||||
plugin.loadConfig();
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&',
|
||||
plugin.getConfig().getString("messages.prefix") + " " +
|
||||
plugin.getConfig().getString("messages.reload")));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
57
src/main/resources/config.yml
Normal file
57
src/main/resources/config.yml
Normal file
@ -0,0 +1,57 @@
|
||||
# UltraStack Configuration
|
||||
# Created by KoopaLabs
|
||||
# Discord: discord.gg/KmHGjaHWct
|
||||
|
||||
# Enable or disable the plugin globally
|
||||
enabled: true
|
||||
|
||||
# World Settings
|
||||
worlds:
|
||||
# Set to 'all' to enable in all worlds
|
||||
# Or list specific worlds where the plugin should work
|
||||
enabled-worlds:
|
||||
- 'all'
|
||||
# Or specify individual worlds:
|
||||
# enabled-worlds:
|
||||
# - 'world'
|
||||
# - 'world_nether'
|
||||
|
||||
# List worlds where the plugin should be disabled
|
||||
disabled-worlds:
|
||||
- 'example_world'
|
||||
|
||||
# Stack Settings
|
||||
stack-settings:
|
||||
# Mode can be 'all' or 'specific'
|
||||
# 'all' - affects all stackable items
|
||||
# 'specific' - only affects items in the items list
|
||||
mode: 'all'
|
||||
|
||||
# Default stack size when mode is 'all'
|
||||
# Set to -1 for infinite stacking
|
||||
default-stack-size: 64000
|
||||
|
||||
# Specific item settings (used when mode is 'specific')
|
||||
items:
|
||||
DIAMOND:
|
||||
enabled: true
|
||||
max-stack: 512
|
||||
STONE:
|
||||
enabled: true
|
||||
max-stack: 999
|
||||
# Add more items as needed
|
||||
|
||||
# Performance Settings
|
||||
performance:
|
||||
# Update stack size on item spawn
|
||||
update-on-spawn: true
|
||||
# Update stack size on item pickup
|
||||
update-on-pickup: true
|
||||
# Update stack size on inventory click
|
||||
update-on-inventory-click: true
|
||||
|
||||
# Messages
|
||||
messages:
|
||||
prefix: '&8[&bUltraStack&8]'
|
||||
reload: '&aConfiguration reloaded successfully!'
|
||||
no-permission: '&cYou don''t have permission to use this command!'
|
18
src/main/resources/plugin.yml
Normal file
18
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,18 @@
|
||||
name: UltraStack
|
||||
version: 0.0.1-ALPHA
|
||||
main: com.koopalabs.ultrastack.UltraStack
|
||||
api-version: '1.21'
|
||||
description: Configurable item stacking plugin with multi-world support
|
||||
author: KoopaLabs
|
||||
website: discord.gg/KmHGjaHWct
|
||||
|
||||
commands:
|
||||
ultrastack:
|
||||
description: Main command for UltraStack plugin
|
||||
usage: /<command> reload
|
||||
permission: ultrastack.admin
|
||||
|
||||
permissions:
|
||||
ultrastack.admin:
|
||||
description: Allows access to UltraStack admin commands
|
||||
default: op
|
Loading…
x
Reference in New Issue
Block a user