Added a configuration (and command), closes #3

This commit is contained in:
SBDeveloper 2022-07-29 15:37:30 +02:00
parent 15148becab
commit b7041f5b2d
12 changed files with 373 additions and 24 deletions

View file

@ -28,8 +28,10 @@ import org.bukkit.Bukkit;
import org.bukkit.map.MapView;
import org.bukkit.plugin.java.JavaPlugin;
import tech.sbdevelopment.mapreflectionapi.api.MapManager;
import tech.sbdevelopment.mapreflectionapi.cmd.MapManagerCMD;
import tech.sbdevelopment.mapreflectionapi.listeners.MapListener;
import tech.sbdevelopment.mapreflectionapi.listeners.PacketListener;
import tech.sbdevelopment.mapreflectionapi.managers.Configuration;
import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil;
import java.util.logging.Level;
@ -67,7 +69,7 @@ public class MapReflectionAPI extends JavaPlugin {
getLogger().info("Made by © Copyright SBDevelopment 2022");
if (!ReflectionUtil.supports(12)) {
getLogger().severe("MapReflectionAPI only supports Minecraft 1.12 - 1.19!");
getLogger().severe("MapReflectionAPI only supports Minecraft 1.12.x - 1.19.x!");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@ -84,20 +86,33 @@ public class MapReflectionAPI extends JavaPlugin {
return;
}
getLogger().info("Loading the configuration...");
Configuration.init(this);
getLogger().info("Loading the commands...");
getCommand("mapmanager").setExecutor(new MapManagerCMD());
getLogger().info("Loading the map manager...");
mapManager = new MapManager();
getLogger().info("Discovering occupied Map IDs...");
if (Configuration.getInstance().isAllowVanilla()) {
getLogger().info("Vanilla Maps are allowed. Discovering occupied Map IDs...");
int occupiedIDs = 0;
for (int s = 0; s < Short.MAX_VALUE; s++) {
try {
MapView view = Bukkit.getMap(s);
if (view != null) mapManager.registerOccupiedID(s);
if (view != null) {
mapManager.registerOccupiedID(s);
occupiedIDs++;
}
} catch (Exception e) {
if (e.getMessage().toLowerCase().contains("invalid map dimension")) {
if (!e.getMessage().toLowerCase().contains("invalid map dimension")) {
getLogger().log(Level.WARNING, e.getMessage(), e);
}
}
}
getLogger().info("Found " + occupiedIDs + " occupied Map IDs. These will not be used.");
}
getLogger().info("Registering the listeners...");
Bukkit.getPluginManager().registerEvents(new MapListener(), this);

View file

@ -27,6 +27,7 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException;
public interface MapController {
@ -70,7 +71,7 @@ public interface MapController {
*
* @param content new {@link ArrayImage} content
*/
void update(ArrayImage content);
void update(@NotNull ArrayImage content);
/**
* Get the content of the controller
@ -94,6 +95,11 @@ public interface MapController {
*/
void sendContent(Player player, boolean withoutQueue);
/**
* Cancels the 'send events' in the queue
*/
void cancelSend();
/**
* Show in a player's inventory
*

View file

@ -27,6 +27,7 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException;
import tech.sbdevelopment.mapreflectionapi.managers.Configuration;
import java.awt.image.BufferedImage;
import java.util.HashSet;
@ -55,9 +56,11 @@ public class MapManager {
* @return The wrapper
*/
public MapWrapper wrapImage(ArrayImage image) {
if (Configuration.getInstance().isImageCache()) {
for (MapWrapper wrapper : MANAGED_MAPS) {
if (wrapper.getContent().equals(image)) return wrapper;
}
}
return wrapNewImage(image);
}
@ -79,8 +82,7 @@ public class MapManager {
* @param wrapper The {@link MapWrapper} to unwrap
*/
public void unwrapImage(MapWrapper wrapper) {
//TODO Cancel IDs
wrapper.controller.cancelSend();
wrapper.getController().clearViewers();
MANAGED_MAPS.remove(wrapper);
}

View file

@ -51,6 +51,15 @@ public class MapSender {
runSender();
}
/**
* Cancels a senderID in the sender queue
*
* @param s The senderID to cancel
*/
public static void cancelID(int s) {
sendQueue.removeIf(queuedMap -> queuedMap.id == s);
}
/**
* Run the sender task
*/
@ -145,6 +154,7 @@ public class MapSender {
ReflectionUtil.sendPacket(player, packet);
}
static final class QueuedMap {
private final int id;
private final ArrayImage image;

View file

@ -29,8 +29,11 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.api.events.MapContentUpdateEvent;
import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException;
import tech.sbdevelopment.mapreflectionapi.managers.Configuration;
import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil;
import java.util.*;
@ -93,19 +96,26 @@ public class MapWrapper {
}
@Override
public void update(ArrayImage content) {
public void update(@NotNull ArrayImage content) {
MapContentUpdateEvent event = new MapContentUpdateEvent(MapWrapper.this, content);
Bukkit.getPluginManager().callEvent(event);
if (Configuration.getInstance().isImageCache()) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper.this.content = duplicate.getContent();
return;
}
}
MapWrapper.this.content = content;
if (event.isSendContent()) {
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
}
@Override
public ArrayImage getContent() {
@ -129,6 +139,13 @@ public class MapWrapper {
}
}
@Override
public void cancelSend() {
for (int s : viewers.values()) {
MapSender.cancelID(s);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;

View file

@ -0,0 +1,62 @@
/*
* This file is part of MapReflectionAPI.
* Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package tech.sbdevelopment.mapreflectionapi.api.events;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import tech.sbdevelopment.mapreflectionapi.api.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.api.MapWrapper;
/**
* This event gets fired when the content of a {@link MapWrapper} is updated
*/
@RequiredArgsConstructor
@Getter
public class MapContentUpdateEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
private final MapWrapper wrapper;
private final ArrayImage content;
private final boolean sendContent = true;
/**
* Construct a new {@link MapContentUpdateEvent}
*
* @param wrapper The wrapper that will be updated
* @param content The content that will be shown
* @param isAsync Is this event called async?
*/
public MapContentUpdateEvent(MapWrapper wrapper, ArrayImage content, boolean isAsync) {
super(isAsync);
this.wrapper = wrapper;
this.content = content;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View file

@ -0,0 +1,63 @@
/*
* This file is part of MapReflectionAPI.
* Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package tech.sbdevelopment.mapreflectionapi.cmd;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import tech.sbdevelopment.mapreflectionapi.managers.Configuration;
import java.util.ArrayList;
import java.util.List;
public class MapManagerCMD implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) {
if (!sender.hasPermission("mapmanager.reload")) {
sender.sendMessage(ChatColor.RED + "You don't have the permissions to use this command!");
return false;
}
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
Configuration.getInstance().reload();
sender.sendMessage(ChatColor.GREEN + "The configuration has been reloaded!");
return true;
}
sender.sendMessage(ChatColor.GREEN + "Usage: " + ChatColor.WHITE + "/mapmanager reload");
return false;
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) {
if (args.length == 1) return StringUtil.copyPartialMatches(args[0], List.of("reload"), new ArrayList<>());
return new ArrayList<>();
}
}

View file

@ -28,6 +28,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.server.MapInitializeEvent;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.managers.Configuration;
public class MapListener implements Listener {
@EventHandler
@ -37,7 +38,12 @@ public class MapListener implements Listener {
@EventHandler
public void onMapInitialize(MapInitializeEvent e) {
if (Configuration.getInstance().isAllowVanilla()) {
int id = e.getMap().getId();
if (id > 0) MapReflectionAPI.getMapManager().registerOccupiedID(id);
if (id > 0) {
MapReflectionAPI.getInstance().getLogger().info("Detected that the Map ID " + id + " got occupied. It will now not be used.");
MapReflectionAPI.getMapManager().registerOccupiedID(id);
}
}
}
}

View file

@ -0,0 +1,57 @@
/*
* This file is part of MapReflectionAPI.
* Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package tech.sbdevelopment.mapreflectionapi.managers;
import lombok.Getter;
import org.bukkit.plugin.java.JavaPlugin;
import tech.sbdevelopment.mapreflectionapi.utils.YamlFile;
public class Configuration {
private static Configuration instance;
private final YamlFile file;
@Getter
private boolean allowVanilla = true;
@Getter
private boolean imageCache = true;
private Configuration(JavaPlugin plugin) {
this.file = new YamlFile(plugin, "config");
reload();
}
public static void init(JavaPlugin plugin) {
instance = new Configuration(plugin);
}
public static Configuration getInstance() {
if (instance == null) throw new IllegalStateException("The plugin is not enabled yet!");
return instance;
}
public void reload() {
allowVanilla = this.file.getFile().getBoolean("allowVanilla");
imageCache = this.file.getFile().getBoolean("imageCache");
}
}

View file

@ -0,0 +1,97 @@
/*
* This file is part of MapReflectionAPI.
* Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package tech.sbdevelopment.mapreflectionapi.utils;
import com.google.common.io.ByteStreams;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.*;
public class YamlFile {
private final JavaPlugin plugin;
private final String name;
private FileConfiguration fileConfiguration;
private File file;
public YamlFile(JavaPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
if (!plugin.getDataFolder().exists()) {
if (!plugin.getDataFolder().mkdir()) {
plugin.getLogger().severe("Couldn't generate the pluginfolder!");
return;
}
}
this.file = new File(plugin.getDataFolder(), name + ".yml");
if (!this.file.exists()) {
try {
if (!this.file.createNewFile()) {
plugin.getLogger().severe("Couldn't generate the " + name + ".yml!");
return;
}
plugin.getLogger().info("Generating the " + name + ".yml...");
} catch (IOException e) {
plugin.getLogger().severe("Couldn't generate the " + name + ".yml!");
return;
}
}
this.fileConfiguration = YamlConfiguration.loadConfiguration(this.file);
}
public void loadDefaults() {
try {
InputStream in = plugin.getResource(name + ".yml");
if (in == null) {
plugin.getLogger().severe("Expected the resource " + name + ".yml, but it was not found in the plugin JAR!");
return;
}
OutputStream out = new FileOutputStream(this.file);
ByteStreams.copy(in, out);
reload();
} catch (IOException e) {
plugin.getLogger().severe("Couldn't load the default " + name + ".yml!");
}
}
public FileConfiguration getFile() {
return this.fileConfiguration;
}
public void save() {
try {
this.fileConfiguration.save(this.file);
} catch (IOException e) {
plugin.getLogger().severe("Couldn't save the " + name + ".yml!");
}
}
public void reload() {
this.fileConfiguration = YamlConfiguration.loadConfiguration(this.file);
}
}

View file

@ -0,0 +1,7 @@
# Is it allowed to use vanilla maps?
# Less efficient, but gives more available map IDs.
allowVanilla: true
# Should the plugin cache images? If so, it will check if the images is already used.
# Less efficient for the first image, but more efficient for the next ones.
imageCache: true

View file

@ -6,3 +6,10 @@ authors: [ inventivetalent, SBDeveloper ]
description: This API helps developer with viewing images on maps.
website: https://sbdevelopment.tech
softdepend: [ BKCommonLib, ProtocolLib ]
commands:
mapmanager:
description: The main command of MapManager.
permissions:
mapmanager.reload:
description: Access to /mapmanager reload
default: op