Compare commits
4 Commits
ec74d5d8f2
...
0aa098ae8f
| Author | SHA1 | Date | |
|---|---|---|---|
| 0aa098ae8f | |||
| a024e42b80 | |||
| 76ddfc95af | |||
| bc43519077 |
+4
-1
@@ -45,8 +45,11 @@ processResources {
|
||||
}
|
||||
}
|
||||
|
||||
// Zielverzeichnis über testServerPluginsDir in gradle.properties oder -PtestServerPluginsDir=... setzen
|
||||
tasks.register('copyJarToTestServer', Exec) {
|
||||
commandLine 'cp', 'build/libs/PixelBlocks-1.0-SNAPSHOT-all.jar', '/home/lars/Documents/Minecraft/Server/pixelblocks/plugins/PixelBlocks-1.0-SNAPSHOT-all.jar'
|
||||
def pluginsDir = providers.gradleProperty('testServerPluginsDir').getOrNull()
|
||||
onlyIf { pluginsDir != null }
|
||||
commandLine 'cp', "build/libs/PixelBlocks-${version}-all.jar", "${pluginsDir}/PixelBlocks-${version}-all.jar"
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
|
||||
@@ -3,10 +3,8 @@ package eu.mhsl.minecraft.pixelblocks;
|
||||
import co.aikar.taskchain.BukkitTaskChainFactory;
|
||||
import co.aikar.taskchain.TaskChain;
|
||||
import co.aikar.taskchain.TaskChainFactory;
|
||||
import eu.mhsl.minecraft.pixelblocks.commands.CreatePixelBlockCommand;
|
||||
import eu.mhsl.minecraft.pixelblocks.commands.DestroyPixelBlocksCommand;
|
||||
import eu.mhsl.minecraft.pixelblocks.commands.ExitWorldCommand;
|
||||
import eu.mhsl.minecraft.pixelblocks.commands.GivePixelBlockCommand;
|
||||
import eu.mhsl.minecraft.pixelblocks.commands.PixelBlocksCommand;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import eu.mhsl.minecraft.pixelblocks.listeners.*;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -15,10 +13,10 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class Main extends JavaPlugin {
|
||||
@@ -28,7 +26,7 @@ public final class Main extends JavaPlugin {
|
||||
|
||||
private static TaskChainFactory taskFactory;
|
||||
|
||||
public final static List<PixelBlock> pixelBlocks = new ArrayList<>();
|
||||
public final static List<PixelBlock> pixelBlocks = new CopyOnWriteArrayList<>();
|
||||
|
||||
public static <T> TaskChain<T> sharedChain(String name) {
|
||||
return taskFactory.newSharedChain(name);
|
||||
@@ -64,7 +62,7 @@ public final class Main extends JavaPlugin {
|
||||
new FallOutOfPixelBlockListener(),
|
||||
new BreakPixelListener(),
|
||||
new PlacePixelBlockListener(),
|
||||
new PreventInventorysListener(),
|
||||
new PreventInventoriesListener(),
|
||||
new ExitPixelWorldListener(),
|
||||
new PreventIllegalBlocksListener(),
|
||||
new BreakPixelBlockListener(),
|
||||
@@ -83,10 +81,10 @@ public final class Main extends JavaPlugin {
|
||||
getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
|
||||
Objects.requireNonNull(getCommand("createpixelblock")).setExecutor(new CreatePixelBlockCommand());
|
||||
Objects.requireNonNull(getCommand("givepixelblock")).setExecutor(new GivePixelBlockCommand());
|
||||
Objects.requireNonNull(getCommand("exitworld")).setExecutor(new ExitWorldCommand());
|
||||
Objects.requireNonNull(getCommand("destroypixelblocks")).setExecutor(new DestroyPixelBlocksCommand());
|
||||
PixelBlocksCommand pixelBlocksCommand = new PixelBlocksCommand();
|
||||
PluginCommand rootCommand = Objects.requireNonNull(getCommand("pixelblocks"));
|
||||
rootCommand.setExecutor(pixelBlocksCommand);
|
||||
rootCommand.setTabCompleter(pixelBlocksCommand);
|
||||
|
||||
Bukkit.addRecipe(PixelBlockItem.getRecipe());
|
||||
}
|
||||
@@ -94,11 +92,8 @@ public final class Main extends JavaPlugin {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld);
|
||||
try {
|
||||
database.close();
|
||||
} catch(SQLException e) {
|
||||
throw new RuntimeException("Failed disabling", e);
|
||||
}
|
||||
taskFactory.shutdown(5, TimeUnit.SECONDS);
|
||||
database.close();
|
||||
}
|
||||
|
||||
public static Main plugin() {
|
||||
|
||||
@@ -9,9 +9,9 @@ public record PixelBlockConfiguration(
|
||||
boolean onlyEditableByOwner
|
||||
) {
|
||||
public static void setDefaults(FileConfiguration config) {
|
||||
config.addDefault(Keys.PixelsPerBlock.key, 16);
|
||||
config.addDefault(Keys.OnlyBreakableByOwners.key, false);
|
||||
config.addDefault(Keys.OnlyEditableByOwners.key, true);
|
||||
config.addDefault(Keys.PixelsPerBlock.getKey(), 16);
|
||||
config.addDefault(Keys.OnlyBreakableByOwners.getKey(), false);
|
||||
config.addDefault(Keys.OnlyEditableByOwners.getKey(), true);
|
||||
config.options().copyDefaults(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,38 @@ import org.bukkit.Location;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class PixelBlockDatabase {
|
||||
private final Connection db;
|
||||
|
||||
// Alle Statement-Zugriffe nach dem Startup laufen ausschließlich auf diesem Thread,
|
||||
// da die geteilten PreparedStatements nicht threadsicher sind.
|
||||
private final ExecutorService executor =
|
||||
Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, "PixelBlocks-Database"));
|
||||
|
||||
private final PreparedStatement getAllPixelBlocks;
|
||||
private final PreparedStatement deletePixelBlock;
|
||||
private final PreparedStatement insertOrReplacePixelBlock;
|
||||
|
||||
private record PixelBlockRow(
|
||||
String uuid,
|
||||
String owner,
|
||||
String worldName,
|
||||
double x,
|
||||
double y,
|
||||
double z,
|
||||
String entryWorldName,
|
||||
double entryX,
|
||||
double entryY,
|
||||
double entryZ,
|
||||
String direction
|
||||
) {
|
||||
}
|
||||
|
||||
public PixelBlockDatabase(String url) {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
@@ -50,52 +74,78 @@ public class PixelBlockDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
deletePixelBlock.close();
|
||||
getAllPixelBlocks.close();
|
||||
insertOrReplacePixelBlock.close();
|
||||
db.close();
|
||||
public void close() {
|
||||
this.executor.shutdown();
|
||||
try {
|
||||
if(!this.executor.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
Main.logger().warning("Database executor did not terminate in time, forcing shutdown");
|
||||
this.executor.shutdownNow();
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
this.executor.shutdownNow();
|
||||
}
|
||||
|
||||
try {
|
||||
this.deletePixelBlock.close();
|
||||
this.getAllPixelBlocks.close();
|
||||
this.insertOrReplacePixelBlock.close();
|
||||
this.db.close();
|
||||
} catch(SQLException e) {
|
||||
Main.logger().log(Level.SEVERE, "Failed closing the database", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deletePixelBlock(PixelBlock pixelBlock) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(Main.plugin(), () -> {
|
||||
String uuid = pixelBlock.getBlockUUID().toString();
|
||||
this.executor.execute(() -> {
|
||||
try {
|
||||
this.deletePixelBlock.setString(1, pixelBlock.getBlockUUID().toString());
|
||||
this.deletePixelBlock.setString(1, uuid);
|
||||
this.deletePixelBlock.executeUpdate();
|
||||
} catch(SQLException e) {
|
||||
throw new RuntimeException("Failed to delete PixelBlock from the database", e);
|
||||
Main.logger().log(Level.SEVERE, String.format("Failed to delete PixelBlock '%s' from the database", uuid), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void savePixelBlock(PixelBlock pixelBlock) {
|
||||
Bukkit.getScheduler().runTask(Main.plugin(), () -> {
|
||||
Location blockLocation = pixelBlock.getPixelBlockLocation();
|
||||
Location entryLocation = pixelBlock.hasLastEntryLocation() ? pixelBlock.getLastEntryLocation() : blockLocation;
|
||||
|
||||
PixelBlockRow row = new PixelBlockRow(
|
||||
pixelBlock.getBlockUUID().toString(),
|
||||
pixelBlock.getOwnerUUID().toString(),
|
||||
blockLocation.getWorld().getName(),
|
||||
blockLocation.getX(),
|
||||
blockLocation.getY(),
|
||||
blockLocation.getZ(),
|
||||
entryLocation.getWorld().getName(),
|
||||
entryLocation.getX(),
|
||||
entryLocation.getY(),
|
||||
entryLocation.getZ(),
|
||||
pixelBlock.getFacingDirection().toString()
|
||||
);
|
||||
|
||||
this.executor.execute(() -> {
|
||||
try {
|
||||
this.insertOrReplacePixelBlock.setString(1, pixelBlock.getBlockUUID().toString());
|
||||
this.insertOrReplacePixelBlock.setString(2, pixelBlock.getOwnerUUID().toString());
|
||||
this.insertOrReplacePixelBlock.setString(1, row.uuid());
|
||||
this.insertOrReplacePixelBlock.setString(2, row.owner());
|
||||
|
||||
this.insertOrReplacePixelBlock.setString(3, pixelBlock.getPixelBlockLocation().getWorld().getName());
|
||||
this.insertOrReplacePixelBlock.setDouble(4, pixelBlock.getPixelBlockLocation().getX());
|
||||
this.insertOrReplacePixelBlock.setDouble(5, pixelBlock.getPixelBlockLocation().getY());
|
||||
this.insertOrReplacePixelBlock.setDouble(6, pixelBlock.getPixelBlockLocation().getZ());
|
||||
this.insertOrReplacePixelBlock.setString(3, row.worldName());
|
||||
this.insertOrReplacePixelBlock.setDouble(4, row.x());
|
||||
this.insertOrReplacePixelBlock.setDouble(5, row.y());
|
||||
this.insertOrReplacePixelBlock.setDouble(6, row.z());
|
||||
|
||||
if(pixelBlock.hasLastEntryLocation()) {
|
||||
this.insertOrReplacePixelBlock.setString(7, pixelBlock.getLastEntryLocation().getWorld().getName());
|
||||
this.insertOrReplacePixelBlock.setDouble(8, pixelBlock.getLastEntryLocation().getX());
|
||||
this.insertOrReplacePixelBlock.setDouble(9, pixelBlock.getLastEntryLocation().getY());
|
||||
this.insertOrReplacePixelBlock.setDouble(10, pixelBlock.getLastEntryLocation().getZ());
|
||||
} else {
|
||||
this.insertOrReplacePixelBlock.setString(7, pixelBlock.getPixelBlockLocation().getWorld().getName());
|
||||
this.insertOrReplacePixelBlock.setDouble(8, pixelBlock.getPixelBlockLocation().getX());
|
||||
this.insertOrReplacePixelBlock.setDouble(9, pixelBlock.getPixelBlockLocation().getY());
|
||||
this.insertOrReplacePixelBlock.setDouble(10, pixelBlock.getPixelBlockLocation().getZ());
|
||||
}
|
||||
this.insertOrReplacePixelBlock.setString(7, row.entryWorldName());
|
||||
this.insertOrReplacePixelBlock.setDouble(8, row.entryX());
|
||||
this.insertOrReplacePixelBlock.setDouble(9, row.entryY());
|
||||
this.insertOrReplacePixelBlock.setDouble(10, row.entryZ());
|
||||
|
||||
this.insertOrReplacePixelBlock.setString(11, pixelBlock.getFacingDirection().toString());
|
||||
this.insertOrReplacePixelBlock.setString(11, row.direction());
|
||||
|
||||
this.insertOrReplacePixelBlock.executeUpdate();
|
||||
} catch(SQLException e) {
|
||||
throw new RuntimeException("Failed to create or update PixelBlock in the database", e);
|
||||
Main.logger().log(Level.SEVERE, String.format("Failed to create or update PixelBlock '%s' in the database", row.uuid()), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -105,27 +155,32 @@ public class PixelBlockDatabase {
|
||||
ResultSet allPixelBlocks = this.getAllPixelBlocks.executeQuery();
|
||||
|
||||
while(allPixelBlocks.next()) {
|
||||
Location blockLocation = new Location(
|
||||
Bukkit.getWorld(allPixelBlocks.getString("locationWorldName")),
|
||||
allPixelBlocks.getDouble("locationX"),
|
||||
allPixelBlocks.getDouble("locationY"),
|
||||
allPixelBlocks.getDouble("locationZ")
|
||||
);
|
||||
String uuid = allPixelBlocks.getString("uuid");
|
||||
try {
|
||||
Location blockLocation = new Location(
|
||||
Bukkit.getWorld(allPixelBlocks.getString("locationWorldName")),
|
||||
allPixelBlocks.getDouble("locationX"),
|
||||
allPixelBlocks.getDouble("locationY"),
|
||||
allPixelBlocks.getDouble("locationZ")
|
||||
);
|
||||
|
||||
Location entryLocation = new Location(
|
||||
Bukkit.getWorld(allPixelBlocks.getString("entryLocationWorldName")),
|
||||
allPixelBlocks.getDouble("entryLocationX"),
|
||||
allPixelBlocks.getDouble("entryLocationY"),
|
||||
allPixelBlocks.getDouble("entryLocationZ")
|
||||
);
|
||||
Location entryLocation = new Location(
|
||||
Bukkit.getWorld(allPixelBlocks.getString("entryLocationWorldName")),
|
||||
allPixelBlocks.getDouble("entryLocationX"),
|
||||
allPixelBlocks.getDouble("entryLocationY"),
|
||||
allPixelBlocks.getDouble("entryLocationZ")
|
||||
);
|
||||
|
||||
Main.pixelBlocks.add(PixelBlock.fromExisting(
|
||||
UUID.fromString(allPixelBlocks.getString("uuid")),
|
||||
UUID.fromString(allPixelBlocks.getString("owner")),
|
||||
blockLocation,
|
||||
Direction.valueOf(allPixelBlocks.getString("direction")),
|
||||
entryLocation
|
||||
));
|
||||
Main.pixelBlocks.add(PixelBlock.fromExisting(
|
||||
UUID.fromString(uuid),
|
||||
UUID.fromString(allPixelBlocks.getString("owner")),
|
||||
blockLocation,
|
||||
Direction.valueOf(allPixelBlocks.getString("direction")),
|
||||
entryLocation
|
||||
));
|
||||
} catch(Exception e) {
|
||||
Main.logger().log(Level.SEVERE, String.format("Failed initializing existing pixelblock '%s'", uuid), e);
|
||||
}
|
||||
}
|
||||
} catch(SQLException e) {
|
||||
throw new RuntimeException("Failed loading PixelBlocks from the database", e);
|
||||
|
||||
@@ -36,6 +36,12 @@ public class PixelBlockItem {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBlockId(@NotNull ItemStack item, @NotNull UUID id) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.getPersistentDataContainer().set(idProperty, PersistentDataType.STRING, id.toString());
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
public static @Nullable BlockInfo getBlockInfo(ItemStack item) {
|
||||
PersistentDataContainer container = item.getItemMeta().getPersistentDataContainer();
|
||||
if(!container.has(idProperty)) return null;
|
||||
@@ -69,7 +75,6 @@ public class PixelBlockItem {
|
||||
ItemStack item = HeadUtil.getCustomTextureHead(itemTexture);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setMaxStackSize(1);
|
||||
meta.itemName(Component.text(emptyBlockUUID.toString()));
|
||||
meta.displayName(Component.text("Leerer Pixelblock"));
|
||||
meta.lore(List.of(
|
||||
Component.text("Der erste Spieler, der den Block platziert wird zum Besitzer des Blocks."),
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CreatePixelBlockCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(sender instanceof Player p) {
|
||||
World playerWorld = p.getWorld();
|
||||
if(PixelBlockWorld.getPixelBlockWorlds().contains(playerWorld)) {
|
||||
p.sendMessage("Pixelblöcke können nicht innerhalb anderen Pixelblöcken erstellt werden.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Location playerLocation = p.getLocation();
|
||||
PixelBlock.createPixelBlock(
|
||||
UUID.randomUUID(),
|
||||
p.getUniqueId(),
|
||||
playerLocation.toBlockLocation(),
|
||||
Direction.south
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CreateSubCommand extends SubCommand {
|
||||
public CreateSubCommand() {
|
||||
super("create", "pixelblocks.command.create", "Erstellt einen neuen Pixelblock an deiner Position.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player player, @NotNull String[] args) {
|
||||
if(PixelBlockWorld.isPixelWorld(player.getWorld())) {
|
||||
player.sendMessage(Component.text("Pixelblöcke können nicht innerhalb anderer Pixelblöcke erstellt werden.", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
PixelBlock.createPixelBlock(
|
||||
UUID.randomUUID(),
|
||||
player.getUniqueId(),
|
||||
player.getLocation().toBlockLocation(),
|
||||
Direction.south
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DestroyAllSubCommand extends SubCommand {
|
||||
public DestroyAllSubCommand() {
|
||||
super("destroyall", "pixelblocks.command.destroyall", "Zerstört alle Pixelblöcke auf dem Server.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player player, @NotNull String[] args) {
|
||||
List<PixelBlock> blocksToDestroy = List.copyOf(Main.pixelBlocks);
|
||||
blocksToDestroy.forEach(pixelBlock -> pixelBlock.destroy(player, true));
|
||||
player.sendMessage(Component.text(String.format("%d Pixelblöcke werden zerstört.", blocksToDestroy.size()), NamedTextColor.GREEN));
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DestroyPixelBlocksCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(sender instanceof Player p) {
|
||||
Main.pixelBlocks.forEach(pixelBlock -> pixelBlock.destroy(Bukkit.getPlayer(pixelBlock.getOwnerUUID())));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ExitSubCommand extends SubCommand {
|
||||
public ExitSubCommand() {
|
||||
super("exit", "pixelblocks.command.exit", "Verlässt den Pixelblock, in dem du dich befindest.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player player, @NotNull String[] args) {
|
||||
if(!PixelBlockWorld.isPixelWorld(player.getWorld())) {
|
||||
player.sendMessage(Component.text("Du befindest dich nicht in einem Pixelblock.", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(player.getWorld());
|
||||
if(pixelBlock == null) {
|
||||
player.sendMessage(Component.text("Dieser Pixelblock konnte nicht gefunden werden.", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
pixelBlock.exitBlock(player);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExitWorldCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(sender instanceof Player p) {
|
||||
World playerWorld = p.getWorld();
|
||||
if(PixelBlockWorld.getOtherWorlds().contains(playerWorld)) {
|
||||
p.sendMessage("Du kannst nur Pixelblöcke verlassen.");
|
||||
return true;
|
||||
}
|
||||
|
||||
PixelBlock currentPixelBlock = PixelBlock.getPixelBlockFromBlockWorld(playerWorld);
|
||||
Objects.requireNonNull(currentPixelBlock);
|
||||
currentPixelBlock.exitBlock(p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.PixelBlockItem;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import static eu.mhsl.minecraft.pixelblocks.PixelBlockItem.getEmptyPixelBlock;
|
||||
|
||||
public class GivePixelBlockCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(sender instanceof Player p) {
|
||||
ItemStack result = getEmptyPixelBlock();
|
||||
ItemMeta itemMeta = result.getItemMeta();
|
||||
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
|
||||
if(!dataContainer.has(PixelBlockItem.idProperty)) return false;
|
||||
String currentId = dataContainer.get(PixelBlockItem.idProperty, PersistentDataType.STRING);
|
||||
Objects.requireNonNull(currentId);
|
||||
if(!UUID.fromString(currentId).equals(PixelBlockItem.emptyBlockUUID)) return false;
|
||||
|
||||
dataContainer.set(PixelBlockItem.idProperty, PersistentDataType.STRING, args[0]);
|
||||
|
||||
result.setItemMeta(itemMeta);
|
||||
|
||||
|
||||
p.getInventory().addItem(result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.PixelBlockItem;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GiveSubCommand extends SubCommand {
|
||||
public GiveSubCommand() {
|
||||
super("give", "pixelblocks.command.give", "Gibt dir ein Pixelblock-Item, optional mit fester UUID.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player player, @NotNull String[] args) {
|
||||
UUID blockId;
|
||||
if(args.length == 0) {
|
||||
blockId = UUID.randomUUID();
|
||||
} else {
|
||||
try {
|
||||
blockId = UUID.fromString(args[0]);
|
||||
} catch(IllegalArgumentException e) {
|
||||
player.sendMessage(Component.text(String.format("'%s' ist keine gültige UUID.", args[0]), NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack item = PixelBlockItem.getEmptyPixelBlock();
|
||||
PixelBlockItem.setBlockId(item, blockId);
|
||||
|
||||
player.getInventory().addItem(item);
|
||||
player.sendMessage(Component.text(String.format("Pixelblock '%s' erhalten.", blockId), NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> tabComplete(@NotNull Player player, @NotNull String[] args) {
|
||||
if(args.length == 1) return List.of("<uuid>");
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PixelBlocksCommand implements CommandExecutor, TabCompleter {
|
||||
private final List<SubCommand> subCommands = List.of(
|
||||
new CreateSubCommand(),
|
||||
new GiveSubCommand(),
|
||||
new ExitSubCommand(),
|
||||
new DestroyAllSubCommand()
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(!(sender instanceof Player player)) {
|
||||
sender.sendMessage(Component.text("Dieser Befehl kann nur von Spielern ausgeführt werden.", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
Optional<SubCommand> subCommand = args.length == 0
|
||||
? Optional.empty()
|
||||
: this.subCommands.stream().filter(sub -> sub.name().equalsIgnoreCase(args[0])).findFirst();
|
||||
|
||||
if(subCommand.isEmpty()) {
|
||||
this.sendUsage(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!player.hasPermission(subCommand.get().permission())) {
|
||||
player.sendMessage(Component.text("Dazu hast du keine Berechtigung.", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
subCommand.get().execute(player, Arrays.copyOfRange(args, 1, args.length));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(!(sender instanceof Player player)) return List.of();
|
||||
|
||||
if(args.length == 1) {
|
||||
return this.subCommands.stream()
|
||||
.filter(sub -> player.hasPermission(sub.permission()))
|
||||
.map(SubCommand::name)
|
||||
.filter(name -> name.startsWith(args[0].toLowerCase()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
return this.subCommands.stream()
|
||||
.filter(sub -> sub.name().equalsIgnoreCase(args[0]))
|
||||
.filter(sub -> player.hasPermission(sub.permission()))
|
||||
.findFirst()
|
||||
.map(sub -> sub.tabComplete(player, Arrays.copyOfRange(args, 1, args.length)))
|
||||
.orElse(List.of());
|
||||
}
|
||||
|
||||
private void sendUsage(@NotNull Player player) {
|
||||
player.sendMessage(Component.text("PixelBlocks-Befehle:", NamedTextColor.GOLD));
|
||||
this.subCommands.stream()
|
||||
.filter(sub -> player.hasPermission(sub.permission()))
|
||||
.forEach(sub -> player.sendMessage(Component.text()
|
||||
.append(Component.text("/pixelblocks " + sub.name(), NamedTextColor.YELLOW))
|
||||
.append(Component.text(" - " + sub.description(), NamedTextColor.GRAY))
|
||||
.build()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.commands;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class SubCommand {
|
||||
private final String name;
|
||||
private final String permission;
|
||||
private final String description;
|
||||
|
||||
protected SubCommand(@NotNull String name, @NotNull String permission, @NotNull String description) {
|
||||
this.name = name;
|
||||
this.permission = permission;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public final @NotNull String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public final @NotNull String permission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public final @NotNull String description() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public abstract void execute(@NotNull Player player, @NotNull String[] args);
|
||||
|
||||
public @NotNull List<String> tabComplete(@NotNull Player player, @NotNull String[] args) {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,6 @@ public class BreakPixelBlockListener implements Listener {
|
||||
Location blockLocation = event.getAttacked().getLocation().toBlockLocation();
|
||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromPlacedLocation(blockLocation);
|
||||
if(pixelBlock == null) return;
|
||||
pixelBlock.destroy(event.getPlayer());
|
||||
pixelBlock.destroy(event.getPlayer(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.CraftItemEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CraftPixelBlockListener implements Listener {
|
||||
@@ -17,14 +13,10 @@ public class CraftPixelBlockListener implements Listener {
|
||||
public void onCraft(CraftItemEvent event) {
|
||||
ItemStack result = event.getInventory().getResult();
|
||||
if(result == null) return;
|
||||
ItemMeta itemMeta = result.getItemMeta();
|
||||
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
|
||||
if(!dataContainer.has(PixelBlockItem.idProperty)) return;
|
||||
String currentId = dataContainer.get(PixelBlockItem.idProperty, PersistentDataType.STRING);
|
||||
Objects.requireNonNull(currentId);
|
||||
if(!UUID.fromString(currentId).equals(PixelBlockItem.emptyBlockUUID)) return;
|
||||
|
||||
dataContainer.set(PixelBlockItem.idProperty, PersistentDataType.STRING, UUID.randomUUID().toString());
|
||||
result.setItemMeta(itemMeta);
|
||||
PixelBlockItem.BlockInfo info = PixelBlockItem.getBlockInfo(result);
|
||||
if(info == null || !info.id().equals(PixelBlockItem.emptyBlockUUID)) return;
|
||||
|
||||
PixelBlockItem.setBlockId(result, UUID.randomUUID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class DiscoverRecipesListener implements Listener {
|
||||
if(!(event.getWhoClicked() instanceof Player player)) return;
|
||||
if(!List.of(Material.HEART_OF_THE_SEA, Material.END_CRYSTAL).contains(clickedItem.getType())) return;
|
||||
if(player.hasDiscoveredRecipe(PixelBlockItem.recipeKey)) return;
|
||||
Main.logger().log(Level.INFO, String.format("%s unlocked tne PixelBlock recipe!", player.getName()));
|
||||
Main.logger().log(Level.INFO, String.format("%s unlocked the PixelBlock recipe!", player.getName()));
|
||||
player.discoverRecipe(PixelBlockItem.recipeKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.listeners;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
||||
import org.bukkit.World;
|
||||
@@ -8,7 +9,6 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.event.player.PlayerPortalEvent;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ExitPixelWorldListener implements Listener {
|
||||
@EventHandler
|
||||
@@ -18,7 +18,10 @@ public class ExitPixelWorldListener implements Listener {
|
||||
|
||||
event.setCancelled(true);
|
||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(pixelBlockWorld);
|
||||
Objects.requireNonNull(pixelBlock);
|
||||
if(pixelBlock == null) {
|
||||
Main.logger().warning("Player used a portal in an unknown pixel world: " + pixelBlockWorld.getName());
|
||||
return;
|
||||
}
|
||||
pixelBlock.exitBlock(event.getPlayer());
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -7,7 +7,6 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class FallOutOfPixelBlockListener implements Listener {
|
||||
@EventHandler
|
||||
@@ -17,7 +16,7 @@ public class FallOutOfPixelBlockListener implements Listener {
|
||||
if(!PixelBlockWorld.isPixelWorld(player.getWorld())) return;
|
||||
|
||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(player.getWorld());
|
||||
Objects.requireNonNull(pixelBlock);
|
||||
if(pixelBlock == null) return;
|
||||
player.teleport(pixelBlock.getPixelWorld().getSpawnLocation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,12 @@ public class PlacePixelBlockListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if(PixelBlock.exists(info.id())) {
|
||||
event.getPlayer().sendMessage(Component.text("Dieser Pixelblock existiert bereits in der Welt!", NamedTextColor.RED));
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Location newBlockLocation = event.getBlock().getLocation();
|
||||
playerWorld.getBlockAt(newBlockLocation).setType(Material.AIR);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class PlacePixelListener implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBuketEmpty(PlayerBucketEmptyEvent event) {
|
||||
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
|
||||
EventCanceling.shouldCancelInPixelBlock(
|
||||
event,
|
||||
event.getBlock().getWorld(),
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import org.bukkit.inventory.CraftingInventory;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
public class PreventInventorysListener implements Listener {
|
||||
public class PreventInventoriesListener implements Listener {
|
||||
@EventHandler
|
||||
public void onInventoryOpen(InventoryOpenEvent event) {
|
||||
EventCanceling.shouldCancelInPixelBlock(
|
||||
+1
-2
@@ -8,7 +8,6 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class QuitWhileInPixelBlockListener implements Listener {
|
||||
@EventHandler
|
||||
@@ -20,7 +19,7 @@ public class QuitWhileInPixelBlockListener implements Listener {
|
||||
World pixelBlockWorld = player.getLocation().getWorld();
|
||||
if(!PixelBlockWorld.isPixelWorld(pixelBlockWorld)) return;
|
||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(pixelBlockWorld);
|
||||
Objects.requireNonNull(pixelBlock);
|
||||
if(pixelBlock == null) return;
|
||||
pixelBlock.exitBlock(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,18 +38,16 @@ public class PixelBlock {
|
||||
private final UUID blockUUID;
|
||||
|
||||
public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
|
||||
UUID worldUUID = PixelBlockWorld.getUUIDFromWorld(world);
|
||||
if(worldUUID == null) return null;
|
||||
return Main.pixelBlocks.stream()
|
||||
.filter(block -> block.blockUUID.equals(getUUIDFromWorld(world)))
|
||||
.filter(block -> block.blockUUID.equals(worldUUID))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public static @Nullable UUID getUUIDFromWorld(@NotNull World world) {
|
||||
try {
|
||||
return UUID.fromString(List.of(world.getName().split("/")).getLast());
|
||||
} catch(IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
public static boolean exists(@NotNull UUID blockUUID) {
|
||||
return Main.pixelBlocks.stream().anyMatch(pixelBlock -> pixelBlock.blockUUID.equals(blockUUID));
|
||||
}
|
||||
|
||||
public static @Nullable PixelBlock getPixelBlockFromPlacedLocation(@NotNull Location placedLocation) {
|
||||
@@ -76,19 +74,15 @@ public class PixelBlock {
|
||||
this.facingDirection = direction;
|
||||
this.lastEntryLocation = lastEntryLocation;
|
||||
|
||||
try {
|
||||
this.pixelWorld = new PixelBlockWorld(this);
|
||||
this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
|
||||
this.pixels = new Pixels(this);
|
||||
this.placeholder = new PixelBlockPlaceholder(this);
|
||||
this.hitbox = new PixelBlockHitbox(this);
|
||||
this.pixelWorld = new PixelBlockWorld(this);
|
||||
this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
|
||||
this.pixels = new Pixels(this);
|
||||
this.placeholder = new PixelBlockPlaceholder(this);
|
||||
this.hitbox = new PixelBlockHitbox(this);
|
||||
|
||||
this.getBlockTaskChain().sync(() -> this.isAccessible = true).execute();
|
||||
this.getBlockTaskChain().sync(() -> this.isAccessible = true).execute();
|
||||
|
||||
Main.logger().info(String.format("Loaded existing pixelblock '%s'", this.blockUUID));
|
||||
} catch(Exception e) {
|
||||
Main.logger().info(String.format("Failed initializing existing pixelblock '%s': %s", this.blockUUID, e.getMessage()));
|
||||
}
|
||||
Main.logger().info(String.format("Loaded existing pixelblock '%s'", this.blockUUID));
|
||||
}
|
||||
|
||||
public static PixelBlock createPixelBlock(UUID blockUUID, UUID ownerUUID, Location pixelBlockLocation, Direction direction) {
|
||||
@@ -96,8 +90,8 @@ public class PixelBlock {
|
||||
}
|
||||
|
||||
private PixelBlock(UUID blockUUID, UUID ownerUUID, Location pixelBlockLocation, Direction direction) {
|
||||
if(Main.pixelBlocks.stream().anyMatch(pixelBlock -> pixelBlock.getBlockUUID().equals(blockUUID)))
|
||||
throw new IllegalStateException(String.format("PixelBlock '%s' ist bereits in der Welt vorhanden!", blockUUID));
|
||||
if(exists(blockUUID))
|
||||
throw new IllegalStateException(String.format("PixelBlock '%s' already exists in the world!", blockUUID));
|
||||
|
||||
this.blockUUID = blockUUID;
|
||||
this.ownerUUID = ownerUUID;
|
||||
@@ -118,12 +112,8 @@ public class PixelBlock {
|
||||
|
||||
this.scheduleEntityUpdate();
|
||||
|
||||
this.getBlockTaskChain()
|
||||
.async(() -> {
|
||||
Main.database().savePixelBlock(this);
|
||||
Main.pixelBlocks.add(this);
|
||||
})
|
||||
.execute();
|
||||
Main.database().savePixelBlock(this);
|
||||
Main.pixelBlocks.add(this);
|
||||
|
||||
this.getBlockTaskChain().sync(() -> this.isAccessible = true).execute();
|
||||
}
|
||||
@@ -139,9 +129,9 @@ public class PixelBlock {
|
||||
}
|
||||
|
||||
this.lastEntryLocation = player.getLocation();
|
||||
Main.database().savePixelBlock(this);
|
||||
|
||||
getBlockTaskChain()
|
||||
.async(() -> Main.database().savePixelBlock(this))
|
||||
.sync(() -> {
|
||||
if(!this.isAccessible) return;
|
||||
player.teleport(this.pixelWorld.getSpawnLocation());
|
||||
@@ -153,7 +143,7 @@ public class PixelBlock {
|
||||
|
||||
public void exitBlock(@NotNull Player player) {
|
||||
this.getBlockTaskChain()
|
||||
.sync(() -> player.teleport(this.lastEntryLocation != null ? this.lastEntryLocation : this.pixelBlockLocation))
|
||||
.sync(() -> player.teleport(this.getReturnLocation()))
|
||||
.sync(() -> this.pixelData = this.pixelWorld.getPixels(this.facingDirection))
|
||||
.current(() -> Main.logger().info(String.format("%s exited PixelBlock", player.getName())))
|
||||
.delay(1)
|
||||
@@ -178,16 +168,17 @@ public class PixelBlock {
|
||||
.execute();
|
||||
}
|
||||
|
||||
public void destroy(Player destroyedBy) {
|
||||
public void destroy(Player destroyedBy, boolean force) {
|
||||
if(!this.isAccessible) return;
|
||||
if(Main.configuration().onlyBreakableByOwner() && !destroyedBy.getUniqueId().equals(ownerUUID)) {
|
||||
destroyedBy.sendMessage("Dieser Pixelblock gehört nicht dir!");
|
||||
if(!force && Main.configuration().onlyBreakableByOwner() && !destroyedBy.getUniqueId().equals(ownerUUID)) {
|
||||
destroyedBy.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
Location returnLocation = this.getReturnLocation();
|
||||
this.pixelWorld.getPlayersInWorld().forEach(p -> {
|
||||
p.sendMessage(Component.text("Der Pixelblock wurde von einem anderen Spieler abgebaut!", NamedTextColor.RED));
|
||||
p.teleport(this.lastEntryLocation);
|
||||
p.teleport(returnLocation);
|
||||
});
|
||||
|
||||
Main.logger().info(String.format("Destroying PixelBlock '%s' at %s", this.blockUUID, pixelBlockLocation));
|
||||
@@ -195,20 +186,19 @@ public class PixelBlock {
|
||||
|
||||
this.pixelWorld.getEntitiesInWorld().stream()
|
||||
.filter(entity -> entity instanceof Item)
|
||||
.forEach(entity -> entity.teleport(this.lastEntryLocation));
|
||||
.forEach(entity -> entity.teleport(returnLocation));
|
||||
|
||||
this.getBlockTaskChain()
|
||||
.sync(() -> {
|
||||
this.removeEntities();
|
||||
World world = this.pixelBlockLocation.getWorld();
|
||||
world.playSound(this.pixelBlockLocation, Sound.BLOCK_COPPER_BULB_BREAK, 1.0F, 30);
|
||||
world.dropItem(this.pixelBlockLocation.add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
|
||||
})
|
||||
.async(() -> {
|
||||
Main.database().deletePixelBlock(this);
|
||||
Main.pixelBlocks.remove(this);
|
||||
world.playSound(this.pixelBlockLocation, Sound.BLOCK_COPPER_BULB_BREAK, 1.0F, 2.0F);
|
||||
world.dropItem(this.getPixelBlockLocation().add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
|
||||
})
|
||||
.execute();
|
||||
|
||||
Main.database().deletePixelBlock(this);
|
||||
Main.pixelBlocks.remove(this);
|
||||
}
|
||||
|
||||
private void removeEntities() {
|
||||
@@ -243,6 +233,12 @@ public class PixelBlock {
|
||||
return this.lastEntryLocation != null;
|
||||
}
|
||||
|
||||
private @NotNull Location getReturnLocation() {
|
||||
return this.hasLastEntryLocation()
|
||||
? this.lastEntryLocation.clone()
|
||||
: this.getPixelBlockLocation().add(0.5, 0, 0.5);
|
||||
}
|
||||
|
||||
public List<PixelBlockWorld.PixelData> getPixelData() {
|
||||
return pixelData;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.MinMaxUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Interaction;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PixelBlockHitbox {
|
||||
private static final NamespacedKey hitboxOfTag = new NamespacedKey(Main.plugin(), "hitbox_of");
|
||||
@@ -29,7 +27,7 @@ public class PixelBlockHitbox {
|
||||
Interaction interaction;
|
||||
if (pixels.size() <= 5) {
|
||||
interaction = (Interaction) absoluteLocation.getWorld().spawnEntity(
|
||||
absoluteLocation.clone().add(0.5, -0, 0.5),
|
||||
absoluteLocation.clone().add(0.5, 0, 0.5),
|
||||
EntityType.INTERACTION
|
||||
);
|
||||
interaction.setInteractionHeight(1);
|
||||
@@ -45,7 +43,7 @@ public class PixelBlockHitbox {
|
||||
|
||||
Location spawnLocation = absoluteLocation.clone().add(
|
||||
((startingX+endingX)/2+0.5)/pixelsPerBlock,
|
||||
(startingY/pixelsPerBlock)-0,
|
||||
startingY/pixelsPerBlock,
|
||||
((startingZ+endingZ)/2+0.5)/pixelsPerBlock
|
||||
);
|
||||
|
||||
@@ -81,19 +79,10 @@ public class PixelBlockHitbox {
|
||||
interaction.setInteractionWidth(width);
|
||||
}
|
||||
|
||||
interaction.getPersistentDataContainer()
|
||||
.set(hitboxOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
||||
EntityTagUtil.tag(interaction, hitboxOfTag, this.parentBlock.getBlockUUID());
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
this.parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1)
|
||||
.stream()
|
||||
.filter(interaction -> interaction.getPersistentDataContainer().has(hitboxOfTag))
|
||||
.filter(interaction -> Objects.equals(
|
||||
interaction.getPersistentDataContainer().get(hitboxOfTag, PersistentDataType.STRING),
|
||||
parentBlock.getBlockUUID().toString()
|
||||
))
|
||||
.forEach(Entity::remove);
|
||||
EntityTagUtil.removeTagged(this.parentBlock.getPixelBlockLocation(), Interaction.class, hitboxOfTag, this.parentBlock.getBlockUUID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataHolder;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.util.Transformation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PixelBlockPlaceholder {
|
||||
@@ -67,20 +64,10 @@ public class PixelBlockPlaceholder {
|
||||
displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
|
||||
placeholders.add(displayContainer);
|
||||
|
||||
placeholders.stream()
|
||||
.map(PersistentDataHolder::getPersistentDataContainer)
|
||||
.forEach(container -> container.set(placeholderOfTag, PersistentDataType.STRING, parentBlockUUID.toString()));
|
||||
placeholders.forEach(placeholder -> EntityTagUtil.tag(placeholder, placeholderOfTag, parentBlockUUID));
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
this.parentBlock.getPixelBlockLocation()
|
||||
.getNearbyEntitiesByType(ItemDisplay.class, 1)
|
||||
.stream()
|
||||
.filter(itemDisplay -> itemDisplay.getPersistentDataContainer().has(placeholderOfTag))
|
||||
.filter(itemDisplay -> Objects.equals(
|
||||
itemDisplay.getPersistentDataContainer().get(placeholderOfTag, PersistentDataType.STRING),
|
||||
parentBlock.getBlockUUID().toString()
|
||||
))
|
||||
.forEach(Entity::remove);
|
||||
EntityTagUtil.removeTagged(this.parentBlock.getPixelBlockLocation(), ItemDisplay.class, placeholderOfTag, this.parentBlock.getBlockUUID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.LocationUtil;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Directional;
|
||||
@@ -20,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PixelBlockWorld {
|
||||
private final PixelBlock parentPixelBlock;
|
||||
@@ -28,16 +30,28 @@ public class PixelBlockWorld {
|
||||
int worldGrassBorderWidth = 10;
|
||||
int pixelsPerBlock = Main.configuration().pixelsPerBlock();
|
||||
|
||||
// Kapselt das Namensschema der Pixelwelten: <dataFolder>/worlds/<blockUUID>
|
||||
private static String worldsBasePath;
|
||||
|
||||
private static @NotNull String getWorldsBasePath() {
|
||||
if(worldsBasePath == null) {
|
||||
worldsBasePath = Main.plugin().getDataFolder().getPath() + File.separator + "worlds";
|
||||
}
|
||||
return worldsBasePath;
|
||||
}
|
||||
|
||||
public static boolean isPixelWorld(@NotNull World world) {
|
||||
return world.getName().startsWith(Main.plugin().getDataFolder().getPath());
|
||||
return world.getName().startsWith(getWorldsBasePath());
|
||||
}
|
||||
|
||||
public static @NotNull List<World> getOtherWorlds() {
|
||||
return Bukkit.getWorlds().stream().filter(w -> !PixelBlockWorld.isPixelWorld(w)).toList();
|
||||
}
|
||||
|
||||
public static @NotNull List<World> getPixelBlockWorlds() {
|
||||
return Bukkit.getWorlds().stream().filter(PixelBlockWorld::isPixelWorld).toList();
|
||||
public static @Nullable UUID getUUIDFromWorld(@NotNull World world) {
|
||||
if(!isPixelWorld(world)) return null;
|
||||
String worldName = world.getName();
|
||||
try {
|
||||
return UUID.fromString(worldName.substring(worldName.lastIndexOf(File.separatorChar) + 1));
|
||||
} catch(IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PixelBlockWorld(PixelBlock parentPixelBlock) {
|
||||
@@ -55,7 +69,7 @@ public class PixelBlockWorld {
|
||||
}
|
||||
|
||||
public @NotNull String getWorldPathName() {
|
||||
return Main.plugin().getDataFolder().getPath() + File.separator + "worlds" + File.separator + this.parentPixelBlock.getBlockUUID();
|
||||
return getWorldsBasePath() + File.separator + this.parentPixelBlock.getBlockUUID();
|
||||
}
|
||||
|
||||
public @NotNull Location getSpawnLocation() {
|
||||
@@ -78,10 +92,6 @@ public class PixelBlockWorld {
|
||||
return new Location(this.world, 0, -60, 0);
|
||||
}
|
||||
|
||||
public @NotNull Location getBuildOriginEnd() {
|
||||
return getBuildOrigin().add(pixelsPerBlock, pixelsPerBlock, pixelsPerBlock);
|
||||
}
|
||||
|
||||
public @NotNull Location getBorderOrigin() {
|
||||
return getBuildOrigin().subtract(1, 1, 1);
|
||||
}
|
||||
@@ -99,31 +109,32 @@ public class PixelBlockWorld {
|
||||
|
||||
public List<PixelData> getPixels(Direction direction) {
|
||||
List<PixelData> pixelData = new ArrayList<>();
|
||||
Location origin = this.getBuildOrigin();
|
||||
int max = pixelsPerBlock - 1;
|
||||
|
||||
for(int x = 0; x < pixelsPerBlock; x++) {
|
||||
for(int y = 0; y < pixelsPerBlock; y++) {
|
||||
for(int z = 0; z < pixelsPerBlock; z++) {
|
||||
Location relativeLocation = new Location(world, x, y, z);
|
||||
int blockX = switch(direction) {
|
||||
case south -> x;
|
||||
case north -> max - x;
|
||||
case east -> max - z;
|
||||
case west -> z;
|
||||
};
|
||||
int blockZ = switch(direction) {
|
||||
case south -> z;
|
||||
case north -> max - z;
|
||||
case east -> x;
|
||||
case west -> max - x;
|
||||
};
|
||||
|
||||
Block block = this.world.getBlockAt(origin.getBlockX() + blockX, origin.getBlockY() + y, origin.getBlockZ() + blockZ);
|
||||
BlockData blockData = block.getBlockData();
|
||||
if(blockData.getMaterial().isAir()) continue;
|
||||
|
||||
Location blockLocation = this.getBuildOrigin();
|
||||
switch(direction) {
|
||||
case south ->
|
||||
blockLocation.add(relativeLocation.x(), relativeLocation.y(), relativeLocation.z());
|
||||
case north ->
|
||||
blockLocation.add((pixelsPerBlock - 1) - relativeLocation.x(), relativeLocation.y(), (pixelsPerBlock - 1) - relativeLocation.z());
|
||||
case east ->
|
||||
blockLocation.add((pixelsPerBlock - 1) - relativeLocation.z(), relativeLocation.y(), relativeLocation.x());
|
||||
case west ->
|
||||
blockLocation.add(relativeLocation.z(), relativeLocation.y(), (pixelsPerBlock - 1) - relativeLocation.x());
|
||||
}
|
||||
BlockData blockData = blockLocation.getBlock().getBlockData();
|
||||
@Nullable Directional directional = blockData instanceof Directional face ? face : null;
|
||||
@Nullable Rotatable rotatable = blockData instanceof Rotatable rotation ? rotation : null;
|
||||
BlockState state = blockLocation.getBlock().getState();
|
||||
|
||||
if(!blockData.getMaterial().isAir()) {
|
||||
pixelData.add(new PixelData(relativeLocation.toVector(), blockData, directional, rotatable, state, (double) 1 / pixelsPerBlock));
|
||||
}
|
||||
pixelData.add(new PixelData(new Vector(x, y, z), blockData, directional, rotatable, block.getState(), (double) 1 / pixelsPerBlock));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,27 +167,38 @@ public class PixelBlockWorld {
|
||||
return world;
|
||||
}
|
||||
|
||||
private static final List<Material> FLOWERS = List.of(
|
||||
Material.DANDELION,
|
||||
Material.POPPY,
|
||||
Material.BLUE_ORCHID,
|
||||
Material.ALLIUM,
|
||||
Material.AZURE_BLUET,
|
||||
Material.RED_TULIP,
|
||||
Material.ORANGE_TULIP,
|
||||
Material.WHITE_TULIP,
|
||||
Material.CORNFLOWER,
|
||||
Material.LILY_OF_THE_VALLEY,
|
||||
Material.SHORT_GRASS,
|
||||
Material.TALL_GRASS
|
||||
);
|
||||
|
||||
private void setBuildingPlatform() {
|
||||
Bukkit.getScheduler().runTask(Main.plugin(), () -> {
|
||||
for(int x = 0; x < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; x++) {
|
||||
for(int z = 0; z < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; z++) {
|
||||
getPlatformOrigin().add(x, 0, z).getBlock().setType(Material.GRASS_BLOCK);
|
||||
}
|
||||
}
|
||||
for(int x = 0; x < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; x++) {
|
||||
for(int z = 0; z < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; z++) {
|
||||
getPlatformOrigin().add(x, -1, z).getBlock().setType(Material.DIRT);
|
||||
int platformSize = (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth;
|
||||
Location platformOrigin = this.getPlatformOrigin();
|
||||
for(int x = 0; x < platformSize; x++) {
|
||||
for(int z = 0; z < platformSize; z++) {
|
||||
platformOrigin.clone().add(x, 0, z).getBlock().setType(Material.GRASS_BLOCK);
|
||||
platformOrigin.clone().add(x, -1, z).getBlock().setType(Material.DIRT);
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < (pixelsPerBlock + 2); x++) {
|
||||
for(int z = 0; z < (pixelsPerBlock + 2); z++) {
|
||||
Location currentLocation = getBorderOrigin().add(x, 0, z);
|
||||
|
||||
if(currentLocation.x() == getBorderOrigin().x() || currentLocation.z() == getBorderOrigin().z()) {
|
||||
currentLocation.getBlock().setType(Material.RED_CONCRETE);
|
||||
} else if(currentLocation.x() == getBorderOrigin().x() + (pixelsPerBlock + 1) || currentLocation.z() == getBorderOrigin().z() + (pixelsPerBlock + 1)) {
|
||||
currentLocation.getBlock().setType(Material.RED_CONCRETE);
|
||||
int borderSize = pixelsPerBlock + 2;
|
||||
Location borderOrigin = this.getBorderOrigin();
|
||||
for(int x = 0; x < borderSize; x++) {
|
||||
for(int z = 0; z < borderSize; z++) {
|
||||
if(x == 0 || z == 0 || x == borderSize - 1 || z == borderSize - 1) {
|
||||
borderOrigin.clone().add(x, 0, z).getBlock().setType(Material.RED_CONCRETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,37 +208,23 @@ public class PixelBlockWorld {
|
||||
if(allowPlacements(location)) return;
|
||||
if(!location.clone().subtract(0, 1, 0).getBlock().getType().equals(Material.GRASS_BLOCK)) return;
|
||||
|
||||
List<Material> flowers = List.of(
|
||||
Material.DANDELION,
|
||||
Material.POPPY,
|
||||
Material.BLUE_ORCHID,
|
||||
Material.ALLIUM,
|
||||
Material.AZURE_BLUET,
|
||||
Material.RED_TULIP,
|
||||
Material.ORANGE_TULIP,
|
||||
Material.WHITE_TULIP,
|
||||
Material.CORNFLOWER,
|
||||
Material.LILY_OF_THE_VALLEY,
|
||||
Material.SHORT_GRASS,
|
||||
Material.TALL_GRASS
|
||||
);
|
||||
if(flowers.contains(location.getBlock().getType())) location.getBlock().setType(Material.AIR);
|
||||
if(FLOWERS.contains(location.getBlock().getType())) location.getBlock().setType(Material.AIR);
|
||||
if(!location.getBlock().getType().equals(Material.AIR)) return;
|
||||
|
||||
if(random.nextInt(30) == 0) {
|
||||
Material randomFlower = flowers.get(random.nextInt(flowers.size()));
|
||||
location.getBlock().setType(randomFlower);
|
||||
location.getBlock().setType(FLOWERS.get(random.nextInt(FLOWERS.size())));
|
||||
}
|
||||
});
|
||||
|
||||
Location portalLocation = this.getPortalLocation();
|
||||
for(int x = 0; x < 4; x++) {
|
||||
for(int y = 0; y < 5; y++) {
|
||||
getPortalLocation().add(x, y, 0).getBlock().setType(Material.OBSIDIAN);
|
||||
portalLocation.clone().add(x, y, 0).getBlock().setType(Material.OBSIDIAN);
|
||||
}
|
||||
}
|
||||
for(int x = 1; x < 3; x++) {
|
||||
for(int y = 1; y < 4; y++) {
|
||||
getPortalLocation().add(x, y, 0).getBlock().setType(Material.NETHER_PORTAL);
|
||||
portalLocation.clone().add(x, y, 0).getBlock().setType(Material.NETHER_PORTAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
||||
|
||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
|
||||
import eu.mhsl.minecraft.pixelblocks.utils.ListUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
@@ -16,7 +17,6 @@ import org.bukkit.block.data.type.EnderChest;
|
||||
import org.bukkit.entity.BlockDisplay;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.util.Transformation;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Pixels {
|
||||
private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin(), "pixel_of");
|
||||
@@ -61,18 +60,16 @@ public class Pixels {
|
||||
transform.getTranslation().set(centerOffset.mul(-1));
|
||||
entity.setTransformation(transform);
|
||||
|
||||
entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
||||
EntityTagUtil.tag(entity, pixelOfTag, this.parentBlock.getBlockUUID());
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
List<BlockDisplay> entities = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1)
|
||||
.stream()
|
||||
.filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag))
|
||||
.filter(blockDisplay -> Objects.equals(
|
||||
blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING),
|
||||
parentBlock.getBlockUUID().toString()
|
||||
))
|
||||
.toList();
|
||||
List<BlockDisplay> entities = EntityTagUtil.findTagged(
|
||||
this.parentBlock.getPixelBlockLocation(),
|
||||
BlockDisplay.class,
|
||||
pixelOfTag,
|
||||
this.parentBlock.getBlockUUID()
|
||||
);
|
||||
|
||||
ListUtil.splitListInParts(10, entities)
|
||||
.forEach(pixels -> parentBlock.getBlockTaskChain()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package eu.mhsl.minecraft.pixelblocks.utils;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EntityTagUtil {
|
||||
public static void tag(@NotNull Entity entity, @NotNull NamespacedKey key, @NotNull UUID id) {
|
||||
entity.getPersistentDataContainer().set(key, PersistentDataType.STRING, id.toString());
|
||||
}
|
||||
|
||||
public static <T extends Entity> @NotNull List<T> findTagged(@NotNull Location center, @NotNull Class<T> type, @NotNull NamespacedKey key, @NotNull UUID id) {
|
||||
String idString = id.toString();
|
||||
return center.getNearbyEntitiesByType(type, 1)
|
||||
.stream()
|
||||
.filter(entity -> Objects.equals(entity.getPersistentDataContainer().get(key, PersistentDataType.STRING), idString))
|
||||
.toList();
|
||||
}
|
||||
|
||||
public static <T extends Entity> void removeTagged(@NotNull Location center, @NotNull Class<T> type, @NotNull NamespacedKey key, @NotNull UUID id) {
|
||||
findTagged(center, type, key, id).forEach(Entity::remove);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public class EventCanceling {
|
||||
if(!PixelBlockWorld.isPixelWorld(world)) return;
|
||||
@Nullable PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(world);
|
||||
if(pixelBlock == null) {
|
||||
Main.logger().warning("Cancelling place event because PixelBlock could not be found: " + world.getName());
|
||||
Main.logger().warning("Cancelling %s event because PixelBlock '%s' could not be found!".formatted(event.getClass().getSimpleName(), world.getName()));
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,20 @@ version: '${version}'
|
||||
main: eu.mhsl.minecraft.pixelblocks.Main
|
||||
api-version: '1.21'
|
||||
commands:
|
||||
createpixelblock:
|
||||
exitworld:
|
||||
givepixelblock:
|
||||
destroypixelblocks:
|
||||
pixelblocks:
|
||||
description: Verwaltung von Pixelblöcken
|
||||
usage: /pixelblocks <create|give|exit|destroyall>
|
||||
aliases: [pb]
|
||||
permissions:
|
||||
pixelblocks.command.create:
|
||||
description: Erlaubt das Erstellen eines Pixelblocks per Befehl
|
||||
default: op
|
||||
pixelblocks.command.give:
|
||||
description: Erlaubt das Geben von Pixelblock-Items
|
||||
default: op
|
||||
pixelblocks.command.exit:
|
||||
description: Erlaubt das Verlassen eines Pixelblocks per Befehl
|
||||
default: true
|
||||
pixelblocks.command.destroyall:
|
||||
description: Erlaubt das Zerstören aller Pixelblöcke
|
||||
default: op
|
||||
|
||||
Reference in New Issue
Block a user