added autoshulker, added support for SelectSettings

This commit is contained in:
Elias Müller 2024-08-24 15:06:21 +02:00
parent a60b6265a8
commit 772687b15d
11 changed files with 285 additions and 18 deletions

View File

@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn;
import eu.mhsl.craftattack.spawn.api.HttpServer;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
import eu.mhsl.craftattack.spawn.appliances.autoShulker.AutoShulker;
import eu.mhsl.craftattack.spawn.appliances.chatMessages.ChatMessages;
import eu.mhsl.craftattack.spawn.appliances.customAdvancements.CustomAdvancements;
import eu.mhsl.craftattack.spawn.appliances.debug.Debug;
@ -64,7 +65,8 @@ public final class Main extends JavaPlugin {
new Fleischerchest(),
new CustomAdvancements(),
new Settings(),
new PortableCrafting()
new PortableCrafting(),
new AutoShulker()
);
Bukkit.getLogger().info("Loading appliances...");

View File

@ -0,0 +1,45 @@
package eu.mhsl.craftattack.spawn.appliances.autoShulker;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
public class AutoShulker extends Appliance {
public boolean tryAutoShulker(Player p, Item item) {
ItemStack itemStack = item.getItemStack();
ItemStack offhandStack = p.getInventory().getItemInOffHand();
if(itemStack.getType().equals(Material.SHULKER_BOX)) return false;
if(!offhandStack.getType().equals(Material.SHULKER_BOX)) return false;
BlockStateMeta blockStateMeta = (BlockStateMeta) offhandStack.getItemMeta();
ShulkerBox shulkerBox = (ShulkerBox) blockStateMeta.getBlockState();
HashMap<Integer, ItemStack> leftOver = shulkerBox.getInventory().addItem(itemStack);
if(leftOver.size() > 1) throw new IllegalStateException("Multiple ItemStacks cannot be processed by AutoShulker!");
if(itemStack.equals(leftOver.get(0))) {
p.sendActionBar(Component.text("Die Shulkerbox ist voll!"));
return false;
}
if(leftOver.isEmpty()) {
item.remove();
}
blockStateMeta.setBlockState(shulkerBox);
offhandStack.setItemMeta(blockStateMeta);
return true;
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new ItemPickupListener());
}
}

View File

@ -0,0 +1,21 @@
package eu.mhsl.craftattack.spawn.appliances.autoShulker;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
import eu.mhsl.craftattack.spawn.appliances.settings.settings.AutoShulkerSetting;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityPickupItemEvent;
public class ItemPickupListener extends ApplianceListener<AutoShulker> {
@EventHandler
public void onPickup(EntityPickupItemEvent event) {
if(event.getEntity() instanceof Player p) {
SelectSetting.Options.Option setting = Settings.instance().getSetting(p, Settings.Key.AutoShulker, SelectSetting.Options.Option.class);
if(setting.is(AutoShulkerSetting.disabled)) return;
if(setting.is(AutoShulkerSetting.notFromPlayers) && event.getItem().getThrower() != null) return;
event.setCancelled(getAppliance().tryAutoShulker(p, event.getItem()));
}
}
}

View File

@ -4,9 +4,9 @@ import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.Setting;
import eu.mhsl.craftattack.spawn.appliances.settings.settings.EnablePortableCraftingSetting;
import eu.mhsl.craftattack.spawn.appliances.settings.settings.ShowJoinAndLeaveMessagesSetting;
import eu.mhsl.craftattack.spawn.appliances.settings.settings.TechnicalTablistSetting;
import eu.mhsl.craftattack.spawn.appliances.settings.listeners.OpenSettingsShortcutListener;
import eu.mhsl.craftattack.spawn.appliances.settings.listeners.SettingsInventoryListener;
import eu.mhsl.craftattack.spawn.appliances.settings.settings.*;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -24,6 +24,8 @@ public class Settings extends Appliance {
TechnicalTab,
ShowJoinAndLeaveMessages,
EnablePortableCrafting,
EnableSettingsShortcut,
AutoShulker,
}
public static Settings instance() {
@ -45,7 +47,9 @@ public class Settings extends Appliance {
List<Setting<?>> settings = List.of(
new TechnicalTablistSetting(),
new ShowJoinAndLeaveMessagesSetting(),
new EnablePortableCraftingSetting()
new EnablePortableCraftingSetting(),
new EnableSettingsShortcutSetting(),
new AutoShulkerSetting()
);
settings.forEach(setting -> setting.initializeFromPlayer(player));
@ -92,7 +96,10 @@ public class Settings extends Appliance {
@Override
@NotNull
protected List<Listener> eventHandlers() {
return List.of(new SettingsInventoryListener());
return List.of(
new SettingsInventoryListener(),
new OpenSettingsShortcutListener()
);
}
@Override

View File

@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.settings.datatypes;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
@ -12,16 +13,10 @@ import java.util.List;
import java.util.Objects;
public abstract class BoolSetting extends Setting<Boolean> {
private boolean state;
public BoolSetting(Settings.Key key) {
super(key);
}
protected abstract String title();
protected abstract String description();
@Override
public void fromStorage(PersistentDataContainer container) {
this.state = container.has(getNamespacedKey())
@ -52,7 +47,7 @@ public abstract class BoolSetting extends Setting<Boolean> {
}
@Override
protected void change() {
protected void change(ClickType clickType) {
this.state = !this.state;
}

View File

@ -0,0 +1,102 @@
package eu.mhsl.craftattack.spawn.appliances.settings.datatypes;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;
public abstract class SelectSetting extends Setting<SelectSetting.Options.Option> {
private final Options options;
public SelectSetting(Settings.Key key, Options options) {
super(key);
this.options = options;
}
public record Options(List<Option> options) {
public record Option(String name, NamespacedKey key) {
public boolean is(Option other) {
return this.equals(other);
}
}
}
protected abstract Material icon();
protected abstract Options.Option defaultValue();
@Override
public ItemMeta buildMeta(ItemMeta meta) {
meta.displayName(Component.text(title(), NamedTextColor.WHITE));
List<Component> lore = new ArrayList<>();
lore.add(Component.text("Status: ", NamedTextColor.DARK_GRAY));
lore.addAll(
this.options.options.stream()
.map(option -> {
boolean isSelected = option.equals(this.state);
return Component.text("> " + option.name, isSelected ? NamedTextColor.GREEN : NamedTextColor.GRAY);
})
.toList()
);
lore.add(Component.empty());
lore.addAll(buildDescription(description()));
meta.lore(lore);
return meta;
}
@Override
protected void change(ClickType clickType) {
int optionModifier = clickType.equals(ClickType.LEFT) ? 1 : -1;
List<Options.Option> options = this.options.options;
this.state = IntStream.range(0, options.size())
.filter(i -> options.get(i).equals(this.state))
.mapToObj(i -> {
int nextIndex = i + optionModifier;
if (nextIndex >= options.size()) {
return options.get(0);
} else if (nextIndex < 0) {
return options.get(options.size() - 1);
} else {
return options.get(nextIndex);
}
})
.findFirst()
.orElseThrow();
}
@Override
protected void fromStorage(PersistentDataContainer container) {
String data = container.has(getNamespacedKey())
? Objects.requireNonNull(container.get(getNamespacedKey(), PersistentDataType.STRING))
: defaultValue().key.asString();
this.state = this.options.options.stream()
.filter(option -> option.key.asString().equals(data))
.findFirst()
.orElse(defaultValue());
}
@Override
protected void toStorage(PersistentDataContainer container, Options.Option value) {
container.set(getNamespacedKey(), PersistentDataType.STRING, value.key.asString());
}
@Override
public Class<?> dataType() {
return Options.Option.class;
}
@Override
public Options.Option state() {
return this.state;
}
}

View File

@ -9,6 +9,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
@ -16,6 +17,7 @@ import org.bukkit.persistence.PersistentDataContainer;
import java.util.List;
public abstract class Setting<TDataType> {
TDataType state;
private final Settings.Key key;
public Setting(Settings.Key key) {
@ -34,8 +36,8 @@ public abstract class Setting<TDataType> {
fromStorage(p.getPersistentDataContainer());
}
public void triggerChange(Player p) {
this.change();
public void triggerChange(Player p, ClickType clickType) {
this.change(clickType);
toStorage(p.getPersistentDataContainer(), this.state());
}
@ -51,9 +53,11 @@ public abstract class Setting<TDataType> {
.toList();
}
protected abstract String title();
protected abstract String description();
protected abstract Material icon();
public abstract ItemMeta buildMeta(ItemMeta meta);
protected abstract void change();
protected abstract void change(ClickType clickType);
protected abstract TDataType defaultValue();
protected abstract void fromStorage(PersistentDataContainer container);
protected abstract void toStorage(PersistentDataContainer container, TDataType value);

View File

@ -0,0 +1,16 @@
package eu.mhsl.craftattack.spawn.appliances.settings.listeners;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
public class OpenSettingsShortcutListener extends ApplianceListener<Settings> {
@EventHandler
public void onItemSwitch(PlayerSwapHandItemsEvent event) {
if(!event.getPlayer().isSneaking()) return;
if(!Settings.instance().getSetting(event.getPlayer(), Settings.Key.EnableSettingsShortcut, Boolean.class)) return;
event.setCancelled(true);
getAppliance().openSettings(event.getPlayer());
}
}

View File

@ -1,6 +1,7 @@
package eu.mhsl.craftattack.spawn.appliances.settings;
package eu.mhsl.craftattack.spawn.appliances.settings.listeners;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -18,7 +19,7 @@ public class SettingsInventoryListener extends ApplianceListener<Settings> {
.filter(setting -> setting.buildItem().equals(event.getCurrentItem()))
.findFirst()
.ifPresent(setting -> {
setting.triggerChange(player);
setting.triggerChange(player, event.getClick());
openInventory.inventory().setItem(event.getSlot(), setting.buildItem());
});
}

View File

@ -0,0 +1,43 @@
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.SelectSetting;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import java.util.List;
import java.util.Locale;
public class AutoShulkerSetting extends SelectSetting {
private static final String namespace = AutoShulkerSetting.class.getSimpleName().toLowerCase(Locale.ROOT);
public static Options.Option disabled = new Options.Option("Deaktiviert", new NamespacedKey(namespace, "disabled"));
public static Options.Option notFromPlayers = new Options.Option("Keine manuell gedroppten Items", new NamespacedKey(namespace, "noplayerdrops"));
public static Options.Option enabled = new Options.Option("Alle", new NamespacedKey(namespace, "enabled"));
public AutoShulkerSetting() {
super(
Settings.Key.AutoShulker,
new Options(List.of(disabled, notFromPlayers, enabled))
);
}
@Override
protected String title() {
return "Shulker in offhand automatisch befüllen";
}
@Override
protected String description() {
return "Wenn eine Shulker in der zweiten Hand gehalten wird, werden alle aufgesammelten Items in dieser abgelegt";
}
@Override
protected Material icon() {
return Material.SHULKER_BOX;
}
@Override
protected Options.Option defaultValue() {
return disabled;
}
}

View File

@ -0,0 +1,31 @@
package eu.mhsl.craftattack.spawn.appliances.settings.settings;
import eu.mhsl.craftattack.spawn.appliances.settings.Settings;
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.BoolSetting;
import org.bukkit.Material;
public class EnableSettingsShortcutSetting extends BoolSetting {
public EnableSettingsShortcutSetting() {
super(Settings.Key.EnableSettingsShortcut);
}
@Override
protected String title() {
return "Einstellungen mit 'Shift + F' öffnen";
}
@Override
protected String description() {
return "Wenn aktiviert öffnet sich dieses Einstellungsmenü durch das Drücken von 'Shift + F' im Spiel (Sneaken und Hand-Wechsel)";
}
@Override
protected Material icon() {
return Material.COMPARATOR;
}
@Override
protected Boolean defaultValue() {
return false;
}
}