Compare commits

...

24 Commits

Author SHA1 Message Date
Ruakij
3f73d15a5a Commended search for existing LinkedBeaconTeleporterItem
(this will lead to more than only 2 linked items)
2021-05-10 00:10:47 +02:00
Ruakij
de1c2816a2 Added missing import 2021-05-10 00:10:01 +02:00
Ruakij
4efa26fe0e Added null-check for lore 2021-05-10 00:09:28 +02:00
Ruakij
8889a16bdc Fixed regex-generation 2021-05-10 00:09:12 +02:00
Ruakij
f8c7672cfa Fixed not using ItemMeta 2021-05-10 00:08:45 +02:00
Ruakij
cb4adc3bc1 Fixed missing ItemMeta assignment 2021-05-10 00:08:25 +02:00
Ruakij
6a4369c527 Fixed Wrong Method-Arguments 2021-05-10 00:07:52 +02:00
Ruakij
a7a8a4b037 Implemented linking of beacons in crafting 2021-05-09 23:24:04 +02:00
Ruakij
b1169f48db Ability to create new LinkedBeaconTeleporterItem 2021-05-09 23:15:25 +02:00
Ruakij
efb18aa711 Fixed spelling :/ 2021-05-09 23:06:01 +02:00
Ruakij
0b538db2a4 Implemented check to detect attempt to place LinkedBeaconTeleporterItem 2021-05-09 23:01:27 +02:00
Ruakij
90443d51f7 Fixed Item returning wrong class 2021-05-09 22:59:46 +02:00
Ruakij
69fcab7bbc Implemented check to detect attempt to break LinkedBeaconTeleporterBlock 2021-05-09 22:55:40 +02:00
Ruakij
376695b466 Implemented check to detect attempt to link 2 beacons 2021-05-09 22:50:54 +02:00
Ruakij
da05087876 Implemented Block-Location de/serialisation 2021-05-09 22:47:10 +02:00
Ruakij
2f621d7a9b Implemented getter for LinkedBeaconTeleporterBlock from Location and teleportId 2021-05-09 22:46:18 +02:00
Ruakij
59e8768ddb Implemented conversion between ItemStack and LinkedBeaconTeleporterItem 2021-05-09 22:40:18 +02:00
Ruakij
48f961fc9c Added Manager for storing Data related to id and location 2021-05-09 22:36:25 +02:00
Ruakij
16a46a6a35 Implemented Objects to work with 2021-05-09 22:00:12 +02:00
Ruakij
abde30e2e1 Implement first Listeners 2021-05-09 21:38:33 +02:00
Ruakij
87d6d4bd70 Created first config with fields 2021-05-09 21:35:24 +02:00
Ruakij
bcd147052c Added static variable for logger-access 2021-05-09 21:07:23 +02:00
Ruakij
92718de5a9 Initialising project 2021-05-09 19:10:10 +02:00
Ruakij
a850972224 Added Maven with papermc 2021-05-09 18:43:05 +02:00
15 changed files with 575 additions and 0 deletions

45
pom.xml Normal file
View File

@ -0,0 +1,45 @@
<?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>eu.ruekov.ruakij</groupId>
<artifactId>LinkedBeaconTeleporters</artifactId>
<version>1.0</version>
<properties>
<author>Ruakij</author>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,41 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class Function {
public static String serialiseBlockLocation(Location loc){
return loc.getWorld().getName()+";"+loc.getBlockX()+";"+loc.getBlockY()+";"+loc.getBlockZ();
}
public static Location deserializeBlockLocation(String serialisedLoc) throws InvalidPropertiesFormatException {
try{
String[] locData = serialisedLoc.split(";");
World world = Bukkit.getWorld(locData[0]);
int x = Integer.parseInt(locData[1]);
int y = Integer.parseInt(locData[2]);
int z = Integer.parseInt(locData[3]);
return new Location(world, x, y, z);
}catch(Exception ex){
throw new InvalidPropertiesFormatException("Could not deserialize BlockLocation '"+ serialisedLoc +"'");
}
}
public static String randomString(String alphabet, int length){
char[] alphabetChars = alphabet.toCharArray();
String str = "";
Random random = new Random();
for(int i=0; i<length; i++){
str += alphabetChars[random.nextInt(alphabet.length())];
}
return str;
}
}

View File

@ -0,0 +1,68 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.LinkedBeaconTeleporterManager;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.listener.OnBlockBreak;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.listener.OnBlockPlace;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.listener.OnPrepareItemCraftEvent;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.logging.Logger;
public class Main extends JavaPlugin {
public static Plugin plugin;
public static FileConfiguration config;
public static FileConfiguration data;
public static Logger log;
public static LinkedBeaconTeleporterManager lbtManager;
public void onEnable() {
log = getLogger();
plugin = this;
PluginManager pluginManager = Bukkit.getPluginManager();
pluginManager.registerEvents(new OnBlockBreak(), this);
pluginManager.registerEvents(new OnBlockPlace(), this);
pluginManager.registerEvents(new OnPrepareItemCraftEvent(), this);
loadConfigs();
lbtManager = new LinkedBeaconTeleporterManager();
log.info("Plugin activated");
}
public void onDisable() {
log.info("Plugin deactivated");
}
public void loadConfigs() {
// config.yml
this.saveDefaultConfig();
config = this.getConfig();
// data.yml
try{
File dataFile = new File("plugins/"+ plugin.getName() +"/data.yml");
dataFile.createNewFile();
data = YamlConfiguration.loadConfiguration(
dataFile
);
}catch (Exception ex){
log.severe("Could not load/create data.yml!");
ex.printStackTrace();
Bukkit.getPluginManager().disablePlugin(this);
}
}
}

View File

@ -0,0 +1,24 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.Function;
import org.bukkit.Location;
/**
* Describes a placed-beacon-teleporter in the world
*/
public abstract class LinkedBeaconTeleporter {
// Persistent id for linked-beacons
public String teleporterId;
LinkedBeaconTeleporter(){
this.teleporterId = Function.randomString("abcdefghijklmnopqrstuvwxyz0123456789", 10);
}
public LinkedBeaconTeleporter(String teleporterId){
this.teleporterId = teleporterId;
}
public String teleporterId(){
return teleporterId;
}
}

View File

@ -0,0 +1,33 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.Main;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class LinkedBeaconTeleporterBlock extends LinkedBeaconTeleporter {
// FIXME: Storing the block like this will block the world from unloading and might be dangerous
Block block;
public LinkedBeaconTeleporterBlock(String teleporterId, Block block) {
super(teleporterId);
this.block = block;
}
public Block block(){
return block;
}
// Conversion methods
public static LinkedBeaconTeleporterBlock getFromLocation(Location loc){
return Main.lbtManager.getLbtBlockFromLocation(loc);
}
public static List<LinkedBeaconTeleporterBlock> getListFromTeleportId(String teleportId){
return Main.lbtManager.getLbtBlocksFromTeleportId(teleportId);
}
}

View File

@ -0,0 +1,40 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.Main;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LinkedBeaconTeleporterItem extends LinkedBeaconTeleporter {
// INFO: Safe to store as its always cloned by bukkit
ItemStack item;
public LinkedBeaconTeleporterItem(ItemStack item){
// Create a new LinkedBeaconTeleporter
super();
this.item = item;
}
public LinkedBeaconTeleporterItem(String teleporterId, ItemStack item) {
super(teleporterId);
this.item = item;
}
public ItemStack item(){
return item;
}
// Conversion methods
public ItemStack toItemStack(){
return Main.lbtManager.getItemStackFromLbtItem(this);
}
public static LinkedBeaconTeleporterItem getFromItemStack(ItemStack itemStack){
return Main.lbtManager.getLbtItemFromItemStack(itemStack);
}
}

View File

@ -0,0 +1,164 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.Function;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.Main;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LinkedBeaconTeleporterManager {
// Stores all placed Beacon-Teleporters for fast access
// TODO: Evaluate necessity of 2 HashMaps with main reason of performance
HashMap<String, List<LinkedBeaconTeleporterBlock>> linkedBeaconTeleporterById = new HashMap();
HashMap<String, LinkedBeaconTeleporterBlock> linkedBeaconTeleporterByLoc = new HashMap();
// Regex to match item-name&lore and extract id (group 1)
String regex;
public LinkedBeaconTeleporterManager(){
Main.log.info("Loading LinkedBeaconTeleporter from config..");
// Construct search item-regex
regex = constructRegex(
Main.config.getString("item.name"),
Main.config.getStringList("item.lore")
);
// Load teleporters
for(String teleporterId : Main.data.getKeys(false)){
ConfigurationSection teleportersData = Main.data.getConfigurationSection(teleporterId);
// New list for this id
ArrayList<LinkedBeaconTeleporterBlock> lbtBlocks = new ArrayList();
for(String blockId : teleportersData.getKeys(false)) {
ConfigurationSection teleporterData = teleportersData.getConfigurationSection(blockId);
// Load location
String serializedLoc = teleporterData.getString("loc");
Location loc;
try {
loc = Function.deserializeBlockLocation(teleporterData.getString("loc"));
} catch (InvalidPropertiesFormatException e) {
Main.log.severe("Could not load location='"+ serializedLoc +"' from "+ teleporterId +" > "+ blockId);
continue;
}
// Check if block is of type Beacon (in case the world was changed without the plugin running)
Block block = loc.getBlock();
if(block.getType() != Material.BEACON){
// Data out of sync! Skipping
Main.log.warning(teleporterId +" > "+ blockId +" at location "+ serializedLoc +" changed and is no longer LinkedBlockTeleporter! (Changed without the plugin running?)");
continue;
}
// Construct block
LinkedBeaconTeleporterBlock lbtBlock = new LinkedBeaconTeleporterBlock(teleporterId, block);
// Add block to id-list
lbtBlocks.add(lbtBlock);
// Save to loc-list
linkedBeaconTeleporterByLoc.put(serializedLoc, lbtBlock);
}
// Save list to id-list
linkedBeaconTeleporterById.put(teleporterId, lbtBlocks);
}
Main.log.info("All done!");
}
// Conversion-methods
public ItemStack getItemStackFromLbtItem(LinkedBeaconTeleporterItem lbtItem){
ItemStack item = new ItemStack(Material.BEACON);
ItemMeta itemMeta = item.getItemMeta();
// Get config-values
String name = Main.config.getString("item.name");
List<String> lore = Main.config.getStringList("item.lore");
// Replace parameters
name = name.replace("%id%", lbtItem.teleporterId);
for(int i=0; i<lore.size(); i++){
lore.set(i,
lore.get(i).replace("%id%", lbtItem.teleporterId)
);
}
// Set meta
itemMeta.setDisplayName(name);
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
return item;
}
public LinkedBeaconTeleporterItem getLbtItemFromItemStack(ItemStack itemStack){
ItemMeta itemMeta = itemStack.getItemMeta();
// Serialize
String nameAndLore = serialiseBeaconItem(
itemMeta.getDisplayName(),
itemMeta.getLore()
);
// Regex match
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(nameAndLore);
if(!matcher.find())
// No data
return null;
LinkedBeaconTeleporterItem lbtItem = new LinkedBeaconTeleporterItem(
matcher.group(1),
itemStack
);
return lbtItem;
}
public LinkedBeaconTeleporterBlock getLbtBlockFromLocation(Location loc){
// Serialize
String serializedLoc = Function.serialiseBlockLocation(loc);
return linkedBeaconTeleporterByLoc.get(serializedLoc);
}
public List<LinkedBeaconTeleporterBlock> getLbtBlocksFromTeleportId(String teleportId){
return linkedBeaconTeleporterById.get(teleportId);
}
String constructRegex(String name, List<String> lore){
// Serialize
String regex = serialiseBeaconItem(name, lore);
// Wrap in regex-quotes
regex = "^\\Q"+ regex +"\\E$";
// Exclude id from regex-quotes and create group
regex = regex.replace("%id%", "\\E(.*)\\Q");
// Remove empty regex-quotes
regex = regex.replace("\\E\\Q", "");
return regex;
}
String serialiseBeaconItem(String name, List<String> lore){
// get name and remove control-chars
String str = name.replace("\\", "\\\\");
if(lore != null){
for (String loreLine : lore) {
// get lore-lines and remove control-chars
str += "\n"+ loreLine.replace("\\", "\\\\");
}
}
return str;
}
}

View File

@ -0,0 +1,11 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.listener;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.LinkedBeaconTeleporterBlock;
import org.bukkit.event.block.BlockBreakEvent;
public class OnBlockBreak {
public static void onBlockBreakEvent(BlockBreakEvent e, LinkedBeaconTeleporterBlock lbtBlock){
}
}

View File

@ -0,0 +1,11 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.listener;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.LinkedBeaconTeleporterItem;
import org.bukkit.event.block.BlockPlaceEvent;
public class OnBlockPlace {
public static void onBlockPlaceEvent(BlockPlaceEvent e, LinkedBeaconTeleporterItem lbtItem){
}
}

View File

@ -0,0 +1,39 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.listener;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.LinkedBeaconTeleporterItem;
import org.bukkit.Material;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public class OnPrepareItemCraftEvent {
public static void onPrepareItemCraftEvent(PrepareItemCraftEvent e){
ItemStack[] matrix = e.getInventory().getMatrix();
// Check if one of provided items is already LinkedBeaconTeleporterItem and use first if found
LinkedBeaconTeleporterItem lbtItem = null;
/*for (ItemStack item : matrix) {
if(item == null) continue;
lbtItem = LinkedBeaconTeleporterItem.getFromItemStack(item);
if(lbtItem != null) break;
}*/
if(lbtItem == null){
// If none is found, create new LinkedBeaconTeleporterItem and set as crafting-result
ItemStack item = new ItemStack(Material.BEACON);
lbtItem = new LinkedBeaconTeleporterItem(item);
}
// Generate ItemStack
ItemStack item = lbtItem.toItemStack();
// Exactly 2
item.setAmount(2);
// Set as crafting-result
e.getInventory().setResult(item);
}
}

View File

@ -0,0 +1,29 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.listener;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.Main;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.LinkedBeaconTeleporterBlock;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
public class OnBlockBreak implements Listener {
@EventHandler(priority = EventPriority.LOW)
public void onBlockBreakEvent(BlockBreakEvent e){
Block block = e.getBlock();
Location loc = block.getLocation();
if(block.getType() == Material.BEACON){
// Check if this beacon is a LinkedBeaconTeleporter
LinkedBeaconTeleporterBlock lbtBlock = LinkedBeaconTeleporterBlock.getFromLocation(loc);
if(lbtBlock != null){
eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.listener.OnBlockBreak.onBlockBreakEvent(e, lbtBlock);
}
}
}
}

View File

@ -0,0 +1,28 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.listener;
import eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.LinkedBeaconTeleporterItem;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
public class OnBlockPlace implements Listener {
@EventHandler(priority = EventPriority.LOW)
public void onBlockPlaceEvent(BlockPlaceEvent e){
ItemStack item = e.getItemInHand();
if(item.getType() == Material.BEACON){
// Check if this beacon is a LinkedBeaconTeleporter
LinkedBeaconTeleporterItem lbtItem = LinkedBeaconTeleporterItem.getFromItemStack(item);
if(lbtItem != null){
eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.listener.OnBlockPlace.onBlockPlaceEvent(e, lbtItem);
}
}
}
}

View File

@ -0,0 +1,31 @@
package eu.ruekov.ruakij.LinkedBeaconTeleporters.listener;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public class OnPrepareItemCraftEvent implements Listener {
@EventHandler(priority = EventPriority.LOW)
public void onPrepareItemCraftEvent(PrepareItemCraftEvent e){
ItemStack[] matrix = e.getInventory().getMatrix();
// Check if 2 beacons are in the crafting-slots
int beaconCount = 0;
for (ItemStack item : matrix) {
if(item == null) continue;
if(item.getType() == Material.BEACON)
beaconCount++;
}
if(beaconCount == 2){
// Exactly 2 beacons found
eu.ruekov.ruakij.LinkedBeaconTeleporters.linkedBeaconTeleporter.listener.OnPrepareItemCraftEvent.onPrepareItemCraftEvent(e);
}
}
}

View File

@ -0,0 +1,7 @@
item: # TODO
# Name & Lore for linked-beacon-blocks
# - Has to include %id% somewhere for identification!
name: '§9BeaconTeleporter'
lore:
- '§8§o%id%'

View File

@ -0,0 +1,4 @@
name: ${artifactId}
version: ${version}
author: ${author}
main: ${groupId}.${artifactId}.Main