Skip to content

Commit

Permalink
Add clipboard
Browse files Browse the repository at this point in the history
  • Loading branch information
56738 committed Oct 5, 2024
1 parent 5c57c17 commit a2e4112
Show file tree
Hide file tree
Showing 26 changed files with 449 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ public <T> boolean put(@NotNull PropertyType<T> type, @NotNull T value) {
return properties.computeIfAbsent(type, PropertyImpl::new).setValue(value);
}

public boolean isEmpty() {
return properties.isEmpty();
}

public void remove(PropertyType<?> type) {
properties.remove(type);
}

public void clear() {
properties.clear();
}

private static class PropertyImpl<T> implements Property<T> {
private final PropertyType<T> type;
private T value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ default boolean canChange(@NotNull Player player) {
}
}

default boolean canCopy(@NotNull Player player) {
return true;
}

/**
* Display name of this property.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.m56738.easyarmorstands.display.menu;

import me.m56738.easyarmorstands.EasyArmorStandsPlugin;
import me.m56738.easyarmorstands.api.menu.MenuClick;
import me.m56738.easyarmorstands.api.property.Property;
import me.m56738.easyarmorstands.api.property.PropertyContainer;
Expand Down Expand Up @@ -39,5 +40,9 @@ protected SimpleItemTemplate prepareTemplate(SimpleItemTemplate template) {

@Override
public void onClick(@NotNull MenuClick click) {
if (click.isShiftClick()) {
EasyArmorStandsPlugin.getInstance().getClipboard(click.player())
.handlePropertyShiftClick(property, click);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,22 @@
import me.m56738.easyarmorstands.capability.CapabilityLoader;
import me.m56738.easyarmorstands.capability.handswap.SwapHandItemsCapability;
import me.m56738.easyarmorstands.capability.tool.ToolCapability;
import me.m56738.easyarmorstands.clipboard.Clipboard;
import me.m56738.easyarmorstands.clipboard.ClipboardListener;
import me.m56738.easyarmorstands.clipboard.ClipboardManager;
import me.m56738.easyarmorstands.color.ColorAxisChangeSlotType;
import me.m56738.easyarmorstands.color.ColorAxisSlotType;
import me.m56738.easyarmorstands.color.ColorIndicatorSlotType;
import me.m56738.easyarmorstands.color.ColorPresetSlotType;
import me.m56738.easyarmorstands.color.ColorSlot;
import me.m56738.easyarmorstands.command.ClipboardCommands;
import me.m56738.easyarmorstands.command.GlobalCommands;
import me.m56738.easyarmorstands.command.HistoryCommands;
import me.m56738.easyarmorstands.command.SessionCommands;
import me.m56738.easyarmorstands.command.annotation.PropertyPermission;
import me.m56738.easyarmorstands.command.parser.NodeValueArgumentParser;
import me.m56738.easyarmorstands.command.processor.ClipboardInjector;
import me.m56738.easyarmorstands.command.processor.ClipboardProcessor;
import me.m56738.easyarmorstands.command.processor.ElementInjector;
import me.m56738.easyarmorstands.command.processor.ElementProcessor;
import me.m56738.easyarmorstands.command.processor.ElementSelectionInjector;
Expand Down Expand Up @@ -147,6 +153,7 @@ public class EasyArmorStandsPlugin extends JavaPlugin implements EasyArmorStands
private MenuProviderImpl menuProvider;
private SessionManagerImpl sessionManager;
private HistoryManager historyManager;
private ClipboardManager clipboardManager;
private UpdateManager updateManager;
private BukkitAudiences adventure;
private LegacyPaperCommandManager<EasCommandSender> commandManager;
Expand Down Expand Up @@ -209,11 +216,13 @@ public void onEnable() {

sessionManager = new SessionManagerImpl();
historyManager = new HistoryManager();
clipboardManager = new ClipboardManager();

SessionListener sessionListener = new SessionListener(this, sessionManager);
getServer().getPluginManager().registerEvents(new MenuListener(), this);
getServer().getPluginManager().registerEvents(sessionListener, this);
getServer().getPluginManager().registerEvents(historyManager, this);
getServer().getPluginManager().registerEvents(new ClipboardListener(clipboardManager), this);
getServer().getPluginManager().registerEvents(new EntityElementListener(), this);
getServer().getScheduler().runTaskTimer(this, sessionManager::update, 0, 1);
getServer().getScheduler().runTaskTimer(this, sessionListener::update, 0, 1);
Expand Down Expand Up @@ -255,6 +264,7 @@ public void onEnable() {
commandManager.parameterInjectorRegistry()
.registerInjector(ValueNode.class, new ValueNodeInjector())
.registerInjector(SessionImpl.class, new SessionInjector())
.registerInjector(Clipboard.class, new ClipboardInjector())
.registerInjector(Element.class, new ElementInjector())
.registerInjector(ElementSelection.class, new ElementSelectionInjector());

Expand All @@ -268,6 +278,7 @@ public void onEnable() {
commandManager.registerCommandPreProcessor(new GroupProcessor());
commandManager.registerCommandPreProcessor(new ElementProcessor());
commandManager.registerCommandPreProcessor(new SessionProcessor());
commandManager.registerCommandPreProcessor(new ClipboardProcessor());

commandManager.registerCommandPostProcessor(new CommandRequirementPostProcessor());

Expand All @@ -282,6 +293,7 @@ public void onEnable() {
annotationParser.parse(new GlobalCommands(commandManager, sessionListener));
annotationParser.parse(new SessionCommands());
annotationParser.parse(new HistoryCommands());
annotationParser.parse(new ClipboardCommands());

if (Bukkit.getPluginManager().isPluginEnabled("WorldGuard")) {
getLogger().info("Enabling WorldGuard integration");
Expand Down Expand Up @@ -515,6 +527,10 @@ public History getHistory(Player player) {
return historyManager.getHistory(player);
}

public Clipboard getClipboard(Player player) {
return clipboardManager.getClipboard(player);
}

@Contract(pure = true)
public <T> T getCapability(Class<T> type) {
return loader.get(type);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package me.m56738.easyarmorstands.clipboard;

import me.m56738.easyarmorstands.api.menu.MenuClick;
import me.m56738.easyarmorstands.api.property.Property;
import me.m56738.easyarmorstands.api.property.PropertyMap;
import me.m56738.easyarmorstands.api.property.type.PropertyType;
import me.m56738.easyarmorstands.message.Message;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.List;

public class Clipboard {
private final Player player;
private final PropertyMap properties = new PropertyMap();

Clipboard(Player player) {
this.player = player;
}

public PropertyMap getProperties() {
return properties;
}

public <T> void handlePropertyShiftClick(Property<T> property, MenuClick click) {
PropertyType<T> type = property.getType();
if (type.canCopy(click.player())) {
properties.put(type, property.getValue());
click.sendMessage(Message.success("easyarmorstands.success.property-copied", type.getName()));
}
}

void removeDisallowed() {
List<PropertyType<?>> types = new ArrayList<>();
properties.forEach(property -> types.add(property.getType()));

for (PropertyType<?> type : types) {
if (!type.canCopy(player)) {
properties.remove(type);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package me.m56738.easyarmorstands.clipboard;

import me.m56738.easyarmorstands.EasyArmorStandsPlugin;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerQuitEvent;

public class ClipboardListener implements Listener {
private final ClipboardManager clipboardManager;

public ClipboardListener(ClipboardManager clipboardManager) {
this.clipboardManager = clipboardManager;
}

@EventHandler
public void onQuit(PlayerQuitEvent event) {
clipboardManager.remove(event.getPlayer());
}

@EventHandler
public void onGameModeChange(PlayerGameModeChangeEvent event) {
EasyArmorStandsPlugin plugin = EasyArmorStandsPlugin.getInstance();
Bukkit.getScheduler().runTask(plugin, () -> clipboardManager.getClipboard(event.getPlayer()).removeDisallowed());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.m56738.easyarmorstands.clipboard;

import org.bukkit.entity.Player;

import java.util.HashMap;
import java.util.Map;

public class ClipboardManager {
private final Map<Player, Clipboard> clipboards = new HashMap<>();

public Clipboard getClipboard(Player player) {
return clipboards.computeIfAbsent(player, Clipboard::new);
}

public void remove(Player player) {
clipboards.remove(player);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package me.m56738.easyarmorstands.command;

import me.m56738.easyarmorstands.api.element.Element;
import me.m56738.easyarmorstands.api.property.Property;
import me.m56738.easyarmorstands.api.property.PropertyContainer;
import me.m56738.easyarmorstands.api.property.type.PropertyType;
import me.m56738.easyarmorstands.clipboard.Clipboard;
import me.m56738.easyarmorstands.command.requirement.RequireElement;
import me.m56738.easyarmorstands.command.requirement.RequireElementSelection;
import me.m56738.easyarmorstands.command.sender.EasPlayer;
import me.m56738.easyarmorstands.command.util.ElementSelection;
import me.m56738.easyarmorstands.message.Message;
import me.m56738.easyarmorstands.permission.Permissions;
import me.m56738.easyarmorstands.util.PropertyCopier;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.CommandDescription;
import org.incendo.cloud.annotations.Permission;

@Command("eas")
public class ClipboardCommands {
@Command("clipboard")
@Permission(Permissions.CLIPBOARD)
@CommandDescription("easyarmorstands.command.description.clipboard")
public void clipboard(EasPlayer sender, Clipboard clipboard) {
if (clipboard.getProperties().isEmpty()) {
sender.sendMessage(Message.warning("easyarmorstands.warning.clipboard-empty"));
return;
}
sender.sendMessage(Message.title("easyarmorstands.title.clipboard"));
clipboard.getProperties().forEach(property -> sender.sendMessage(Component.text()
.content("* ")
.color(NamedTextColor.GRAY)
.append(describeProperty(property))));
sender.sendMessage(Message.hint("easyarmorstands.hint.paste-clipboard", Message.command("/eas paste")));
sender.sendMessage(Message.hint("easyarmorstands.hint.clear-clipboard", Message.command("/eas clipboard clear")));
}

private <T> Component describeProperty(Property<T> property) {
PropertyType<T> type = property.getType();
return Component.text()
.append(type.getName())
.append(Component.text(": "))
.append(type.getValueComponent(property.getValue()))
.build();
}

@Command("clipboard clear")
@Permission(Permissions.CLIPBOARD)
@CommandDescription("easyarmorstands.command.description.clipboard.clear")
public void clear(EasPlayer sender, Clipboard clipboard) {
if (clipboard.getProperties().isEmpty()) {
sender.sendMessage(Message.warning("easyarmorstands.warning.clipboard-empty"));
} else {
clipboard.getProperties().clear();
sender.sendMessage(Message.success("easyarmorstands.success.clipboard-cleared"));
}
}

@Command("copy")
@Permission(Permissions.CLIPBOARD)
@CommandDescription("easyarmorstands.command.description.copy")
@RequireElement
public void copy(EasPlayer sender, Clipboard clipboard, Element element) {
element.getProperties().forEach(property -> {
if (property.getType().canCopy(sender.player())) {
copyProperty(clipboard, property);
}
});
sender.sendMessage(Message.success("easyarmorstands.success.clipboard-copied"));
sender.sendMessage(Message.hint("easyarmorstands.hint.show-clipboard", Message.command("/eas clipboard")));
sender.sendMessage(Message.hint("easyarmorstands.hint.paste-clipboard", Message.command("/eas paste")));
}

private <T> void copyProperty(Clipboard clipboard, Property<T> property) {
clipboard.getProperties().put(property.getType(), property.getValue());
}

@Command("paste")
@Permission(Permissions.CLIPBOARD)
@CommandDescription("easyarmorstands.command.description.paste")
@RequireElementSelection
public void paste(EasPlayer sender, Clipboard clipboard, ElementSelection selection) {
if (clipboard.getProperties().isEmpty()) {
sender.sendMessage(Message.error("easyarmorstands.error.clipboard-empty"));
sender.sendMessage(Message.hint("easyarmorstands.hint.copy-property"));
sender.sendMessage(Message.hint("easyarmorstands.hint.copy-all-properties", Message.command("/eas copy")));
return;
}

PropertyCopier copier = new PropertyCopier();
PropertyContainer properties = selection.properties(sender);
copier.copyProperties(properties, clipboard.getProperties());
properties.commit(Message.component("easyarmorstands.history.clipboard-pasted"));

if (copier.getSuccessCount() > 0) {
sender.sendMessage(Message.success("easyarmorstands.success.clipboard-pasted"));
if (copier.getFailureCount() > 0) {
sender.sendMessage(Message.warning("easyarmorstands.warning.clipboard-partial"));
}
} else if (copier.getFailureCount() > 0) {
sender.sendMessage(Message.error("easyarmorstands.error.clipboard-failed"));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.m56738.easyarmorstands.command.processor;

import me.m56738.easyarmorstands.clipboard.Clipboard;
import me.m56738.easyarmorstands.command.sender.EasCommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.injection.ParameterInjector;
import org.incendo.cloud.util.annotation.AnnotationAccessor;

import static me.m56738.easyarmorstands.command.processor.ClipboardProcessor.clipboardKey;

public class ClipboardInjector implements ParameterInjector<EasCommandSender, Clipboard> {
@Override
public @Nullable Clipboard create(@NonNull CommandContext<EasCommandSender> context, @NonNull AnnotationAccessor annotationAccessor) {
return context.getOrDefault(clipboardKey(), null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.m56738.easyarmorstands.command.processor;

import me.m56738.easyarmorstands.clipboard.Clipboard;
import me.m56738.easyarmorstands.command.sender.EasCommandSender;
import me.m56738.easyarmorstands.command.sender.EasPlayer;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.execution.preprocessor.CommandPreprocessingContext;
import org.incendo.cloud.execution.preprocessor.CommandPreprocessor;
import org.incendo.cloud.key.CloudKey;

import static org.incendo.cloud.key.CloudKey.cloudKey;

public class ClipboardProcessor implements CommandPreprocessor<EasCommandSender> {
private static final CloudKey<Clipboard> KEY = cloudKey("clipboard", Clipboard.class);

public static CloudKey<Clipboard> clipboardKey() {
return KEY;
}

@Override
public void accept(@NonNull CommandPreprocessingContext<EasCommandSender> context) {
CommandContext<EasCommandSender> commandContext = context.commandContext();
EasCommandSender sender = commandContext.sender();
if (sender instanceof EasPlayer) {
Clipboard clipboard = ((EasPlayer) sender).clipboard();
commandContext.set(KEY, clipboard);
}
}
}
Loading

0 comments on commit a2e4112

Please sign in to comment.