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) {
|
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 {
|
shadowJar {
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ package eu.mhsl.minecraft.pixelblocks;
|
|||||||
import co.aikar.taskchain.BukkitTaskChainFactory;
|
import co.aikar.taskchain.BukkitTaskChainFactory;
|
||||||
import co.aikar.taskchain.TaskChain;
|
import co.aikar.taskchain.TaskChain;
|
||||||
import co.aikar.taskchain.TaskChainFactory;
|
import co.aikar.taskchain.TaskChainFactory;
|
||||||
import eu.mhsl.minecraft.pixelblocks.commands.CreatePixelBlockCommand;
|
import eu.mhsl.minecraft.pixelblocks.commands.PixelBlocksCommand;
|
||||||
import eu.mhsl.minecraft.pixelblocks.commands.DestroyPixelBlocksCommand;
|
import org.bukkit.command.PluginCommand;
|
||||||
import eu.mhsl.minecraft.pixelblocks.commands.ExitWorldCommand;
|
|
||||||
import eu.mhsl.minecraft.pixelblocks.commands.GivePixelBlockCommand;
|
|
||||||
import eu.mhsl.minecraft.pixelblocks.listeners.*;
|
import eu.mhsl.minecraft.pixelblocks.listeners.*;
|
||||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlock;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@@ -15,10 +13,10 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public final class Main extends JavaPlugin {
|
public final class Main extends JavaPlugin {
|
||||||
@@ -28,7 +26,7 @@ public final class Main extends JavaPlugin {
|
|||||||
|
|
||||||
private static TaskChainFactory taskFactory;
|
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) {
|
public static <T> TaskChain<T> sharedChain(String name) {
|
||||||
return taskFactory.newSharedChain(name);
|
return taskFactory.newSharedChain(name);
|
||||||
@@ -64,7 +62,7 @@ public final class Main extends JavaPlugin {
|
|||||||
new FallOutOfPixelBlockListener(),
|
new FallOutOfPixelBlockListener(),
|
||||||
new BreakPixelListener(),
|
new BreakPixelListener(),
|
||||||
new PlacePixelBlockListener(),
|
new PlacePixelBlockListener(),
|
||||||
new PreventInventorysListener(),
|
new PreventInventoriesListener(),
|
||||||
new ExitPixelWorldListener(),
|
new ExitPixelWorldListener(),
|
||||||
new PreventIllegalBlocksListener(),
|
new PreventIllegalBlocksListener(),
|
||||||
new BreakPixelBlockListener(),
|
new BreakPixelBlockListener(),
|
||||||
@@ -83,10 +81,10 @@ public final class Main extends JavaPlugin {
|
|||||||
getServer().getPluginManager().registerEvents(listener, plugin);
|
getServer().getPluginManager().registerEvents(listener, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Objects.requireNonNull(getCommand("createpixelblock")).setExecutor(new CreatePixelBlockCommand());
|
PixelBlocksCommand pixelBlocksCommand = new PixelBlocksCommand();
|
||||||
Objects.requireNonNull(getCommand("givepixelblock")).setExecutor(new GivePixelBlockCommand());
|
PluginCommand rootCommand = Objects.requireNonNull(getCommand("pixelblocks"));
|
||||||
Objects.requireNonNull(getCommand("exitworld")).setExecutor(new ExitWorldCommand());
|
rootCommand.setExecutor(pixelBlocksCommand);
|
||||||
Objects.requireNonNull(getCommand("destroypixelblocks")).setExecutor(new DestroyPixelBlocksCommand());
|
rootCommand.setTabCompleter(pixelBlocksCommand);
|
||||||
|
|
||||||
Bukkit.addRecipe(PixelBlockItem.getRecipe());
|
Bukkit.addRecipe(PixelBlockItem.getRecipe());
|
||||||
}
|
}
|
||||||
@@ -94,11 +92,8 @@ public final class Main extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld);
|
Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld);
|
||||||
try {
|
taskFactory.shutdown(5, TimeUnit.SECONDS);
|
||||||
database.close();
|
database.close();
|
||||||
} catch(SQLException e) {
|
|
||||||
throw new RuntimeException("Failed disabling", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Main plugin() {
|
public static Main plugin() {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ public record PixelBlockConfiguration(
|
|||||||
boolean onlyEditableByOwner
|
boolean onlyEditableByOwner
|
||||||
) {
|
) {
|
||||||
public static void setDefaults(FileConfiguration config) {
|
public static void setDefaults(FileConfiguration config) {
|
||||||
config.addDefault(Keys.PixelsPerBlock.key, 16);
|
config.addDefault(Keys.PixelsPerBlock.getKey(), 16);
|
||||||
config.addDefault(Keys.OnlyBreakableByOwners.key, false);
|
config.addDefault(Keys.OnlyBreakableByOwners.getKey(), false);
|
||||||
config.addDefault(Keys.OnlyEditableByOwners.key, true);
|
config.addDefault(Keys.OnlyEditableByOwners.getKey(), true);
|
||||||
config.options().copyDefaults(true);
|
config.options().copyDefaults(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,38 @@ import org.bukkit.Location;
|
|||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.UUID;
|
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 {
|
public class PixelBlockDatabase {
|
||||||
private final Connection db;
|
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 getAllPixelBlocks;
|
||||||
private final PreparedStatement deletePixelBlock;
|
private final PreparedStatement deletePixelBlock;
|
||||||
private final PreparedStatement insertOrReplacePixelBlock;
|
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) {
|
public PixelBlockDatabase(String url) {
|
||||||
try {
|
try {
|
||||||
Class.forName("org.sqlite.JDBC");
|
Class.forName("org.sqlite.JDBC");
|
||||||
@@ -50,52 +74,78 @@ public class PixelBlockDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws SQLException {
|
public void close() {
|
||||||
deletePixelBlock.close();
|
this.executor.shutdown();
|
||||||
getAllPixelBlocks.close();
|
try {
|
||||||
insertOrReplacePixelBlock.close();
|
if(!this.executor.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||||
db.close();
|
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) {
|
public void deletePixelBlock(PixelBlock pixelBlock) {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(Main.plugin(), () -> {
|
String uuid = pixelBlock.getBlockUUID().toString();
|
||||||
|
this.executor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
this.deletePixelBlock.setString(1, pixelBlock.getBlockUUID().toString());
|
this.deletePixelBlock.setString(1, uuid);
|
||||||
this.deletePixelBlock.executeUpdate();
|
this.deletePixelBlock.executeUpdate();
|
||||||
} catch(SQLException e) {
|
} 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) {
|
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 {
|
try {
|
||||||
this.insertOrReplacePixelBlock.setString(1, pixelBlock.getBlockUUID().toString());
|
this.insertOrReplacePixelBlock.setString(1, row.uuid());
|
||||||
this.insertOrReplacePixelBlock.setString(2, pixelBlock.getOwnerUUID().toString());
|
this.insertOrReplacePixelBlock.setString(2, row.owner());
|
||||||
|
|
||||||
this.insertOrReplacePixelBlock.setString(3, pixelBlock.getPixelBlockLocation().getWorld().getName());
|
this.insertOrReplacePixelBlock.setString(3, row.worldName());
|
||||||
this.insertOrReplacePixelBlock.setDouble(4, pixelBlock.getPixelBlockLocation().getX());
|
this.insertOrReplacePixelBlock.setDouble(4, row.x());
|
||||||
this.insertOrReplacePixelBlock.setDouble(5, pixelBlock.getPixelBlockLocation().getY());
|
this.insertOrReplacePixelBlock.setDouble(5, row.y());
|
||||||
this.insertOrReplacePixelBlock.setDouble(6, pixelBlock.getPixelBlockLocation().getZ());
|
this.insertOrReplacePixelBlock.setDouble(6, row.z());
|
||||||
|
|
||||||
if(pixelBlock.hasLastEntryLocation()) {
|
this.insertOrReplacePixelBlock.setString(7, row.entryWorldName());
|
||||||
this.insertOrReplacePixelBlock.setString(7, pixelBlock.getLastEntryLocation().getWorld().getName());
|
this.insertOrReplacePixelBlock.setDouble(8, row.entryX());
|
||||||
this.insertOrReplacePixelBlock.setDouble(8, pixelBlock.getLastEntryLocation().getX());
|
this.insertOrReplacePixelBlock.setDouble(9, row.entryY());
|
||||||
this.insertOrReplacePixelBlock.setDouble(9, pixelBlock.getLastEntryLocation().getY());
|
this.insertOrReplacePixelBlock.setDouble(10, row.entryZ());
|
||||||
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(11, pixelBlock.getFacingDirection().toString());
|
this.insertOrReplacePixelBlock.setString(11, row.direction());
|
||||||
|
|
||||||
this.insertOrReplacePixelBlock.executeUpdate();
|
this.insertOrReplacePixelBlock.executeUpdate();
|
||||||
} catch(SQLException e) {
|
} 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();
|
ResultSet allPixelBlocks = this.getAllPixelBlocks.executeQuery();
|
||||||
|
|
||||||
while(allPixelBlocks.next()) {
|
while(allPixelBlocks.next()) {
|
||||||
Location blockLocation = new Location(
|
String uuid = allPixelBlocks.getString("uuid");
|
||||||
Bukkit.getWorld(allPixelBlocks.getString("locationWorldName")),
|
try {
|
||||||
allPixelBlocks.getDouble("locationX"),
|
Location blockLocation = new Location(
|
||||||
allPixelBlocks.getDouble("locationY"),
|
Bukkit.getWorld(allPixelBlocks.getString("locationWorldName")),
|
||||||
allPixelBlocks.getDouble("locationZ")
|
allPixelBlocks.getDouble("locationX"),
|
||||||
);
|
allPixelBlocks.getDouble("locationY"),
|
||||||
|
allPixelBlocks.getDouble("locationZ")
|
||||||
|
);
|
||||||
|
|
||||||
Location entryLocation = new Location(
|
Location entryLocation = new Location(
|
||||||
Bukkit.getWorld(allPixelBlocks.getString("entryLocationWorldName")),
|
Bukkit.getWorld(allPixelBlocks.getString("entryLocationWorldName")),
|
||||||
allPixelBlocks.getDouble("entryLocationX"),
|
allPixelBlocks.getDouble("entryLocationX"),
|
||||||
allPixelBlocks.getDouble("entryLocationY"),
|
allPixelBlocks.getDouble("entryLocationY"),
|
||||||
allPixelBlocks.getDouble("entryLocationZ")
|
allPixelBlocks.getDouble("entryLocationZ")
|
||||||
);
|
);
|
||||||
|
|
||||||
Main.pixelBlocks.add(PixelBlock.fromExisting(
|
Main.pixelBlocks.add(PixelBlock.fromExisting(
|
||||||
UUID.fromString(allPixelBlocks.getString("uuid")),
|
UUID.fromString(uuid),
|
||||||
UUID.fromString(allPixelBlocks.getString("owner")),
|
UUID.fromString(allPixelBlocks.getString("owner")),
|
||||||
blockLocation,
|
blockLocation,
|
||||||
Direction.valueOf(allPixelBlocks.getString("direction")),
|
Direction.valueOf(allPixelBlocks.getString("direction")),
|
||||||
entryLocation
|
entryLocation
|
||||||
));
|
));
|
||||||
|
} catch(Exception e) {
|
||||||
|
Main.logger().log(Level.SEVERE, String.format("Failed initializing existing pixelblock '%s'", uuid), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
throw new RuntimeException("Failed loading PixelBlocks from the database", 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) {
|
public static @Nullable BlockInfo getBlockInfo(ItemStack item) {
|
||||||
PersistentDataContainer container = item.getItemMeta().getPersistentDataContainer();
|
PersistentDataContainer container = item.getItemMeta().getPersistentDataContainer();
|
||||||
if(!container.has(idProperty)) return null;
|
if(!container.has(idProperty)) return null;
|
||||||
@@ -69,7 +75,6 @@ public class PixelBlockItem {
|
|||||||
ItemStack item = HeadUtil.getCustomTextureHead(itemTexture);
|
ItemStack item = HeadUtil.getCustomTextureHead(itemTexture);
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
meta.setMaxStackSize(1);
|
meta.setMaxStackSize(1);
|
||||||
meta.itemName(Component.text(emptyBlockUUID.toString()));
|
|
||||||
meta.displayName(Component.text("Leerer Pixelblock"));
|
meta.displayName(Component.text("Leerer Pixelblock"));
|
||||||
meta.lore(List.of(
|
meta.lore(List.of(
|
||||||
Component.text("Der erste Spieler, der den Block platziert wird zum Besitzer des Blocks."),
|
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();
|
Location blockLocation = event.getAttacked().getLocation().toBlockLocation();
|
||||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromPlacedLocation(blockLocation);
|
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromPlacedLocation(blockLocation);
|
||||||
if(pixelBlock == null) return;
|
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.Listener;
|
||||||
import org.bukkit.event.inventory.CraftItemEvent;
|
import org.bukkit.event.inventory.CraftItemEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
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;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class CraftPixelBlockListener implements Listener {
|
public class CraftPixelBlockListener implements Listener {
|
||||||
@@ -17,14 +13,10 @@ public class CraftPixelBlockListener implements Listener {
|
|||||||
public void onCraft(CraftItemEvent event) {
|
public void onCraft(CraftItemEvent event) {
|
||||||
ItemStack result = event.getInventory().getResult();
|
ItemStack result = event.getInventory().getResult();
|
||||||
if(result == null) return;
|
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());
|
PixelBlockItem.BlockInfo info = PixelBlockItem.getBlockInfo(result);
|
||||||
result.setItemMeta(itemMeta);
|
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(!(event.getWhoClicked() instanceof Player player)) return;
|
||||||
if(!List.of(Material.HEART_OF_THE_SEA, Material.END_CRYSTAL).contains(clickedItem.getType())) return;
|
if(!List.of(Material.HEART_OF_THE_SEA, Material.END_CRYSTAL).contains(clickedItem.getType())) return;
|
||||||
if(player.hasDiscoveredRecipe(PixelBlockItem.recipeKey)) 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);
|
player.discoverRecipe(PixelBlockItem.recipeKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package eu.mhsl.minecraft.pixelblocks.listeners;
|
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.PixelBlock;
|
||||||
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
import eu.mhsl.minecraft.pixelblocks.pixelblock.PixelBlockWorld;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@@ -8,7 +9,6 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.entity.EntityPortalEvent;
|
import org.bukkit.event.entity.EntityPortalEvent;
|
||||||
import org.bukkit.event.player.PlayerPortalEvent;
|
import org.bukkit.event.player.PlayerPortalEvent;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class ExitPixelWorldListener implements Listener {
|
public class ExitPixelWorldListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
@@ -18,7 +18,10 @@ public class ExitPixelWorldListener implements Listener {
|
|||||||
|
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(pixelBlockWorld);
|
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());
|
pixelBlock.exitBlock(event.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -7,7 +7,6 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class FallOutOfPixelBlockListener implements Listener {
|
public class FallOutOfPixelBlockListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
@@ -17,7 +16,7 @@ public class FallOutOfPixelBlockListener implements Listener {
|
|||||||
if(!PixelBlockWorld.isPixelWorld(player.getWorld())) return;
|
if(!PixelBlockWorld.isPixelWorld(player.getWorld())) return;
|
||||||
|
|
||||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(player.getWorld());
|
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(player.getWorld());
|
||||||
Objects.requireNonNull(pixelBlock);
|
if(pixelBlock == null) return;
|
||||||
player.teleport(pixelBlock.getPixelWorld().getSpawnLocation());
|
player.teleport(pixelBlock.getPixelWorld().getSpawnLocation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ public class PlacePixelBlockListener implements Listener {
|
|||||||
return;
|
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();
|
Location newBlockLocation = event.getBlock().getLocation();
|
||||||
playerWorld.getBlockAt(newBlockLocation).setType(Material.AIR);
|
playerWorld.getBlockAt(newBlockLocation).setType(Material.AIR);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class PlacePixelListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBuketEmpty(PlayerBucketEmptyEvent event) {
|
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
|
||||||
EventCanceling.shouldCancelInPixelBlock(
|
EventCanceling.shouldCancelInPixelBlock(
|
||||||
event,
|
event,
|
||||||
event.getBlock().getWorld(),
|
event.getBlock().getWorld(),
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import org.bukkit.inventory.CraftingInventory;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.PlayerInventory;
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
|
|
||||||
public class PreventInventorysListener implements Listener {
|
public class PreventInventoriesListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onInventoryOpen(InventoryOpenEvent event) {
|
public void onInventoryOpen(InventoryOpenEvent event) {
|
||||||
EventCanceling.shouldCancelInPixelBlock(
|
EventCanceling.shouldCancelInPixelBlock(
|
||||||
+1
-2
@@ -8,7 +8,6 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class QuitWhileInPixelBlockListener implements Listener {
|
public class QuitWhileInPixelBlockListener implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
@@ -20,7 +19,7 @@ public class QuitWhileInPixelBlockListener implements Listener {
|
|||||||
World pixelBlockWorld = player.getLocation().getWorld();
|
World pixelBlockWorld = player.getLocation().getWorld();
|
||||||
if(!PixelBlockWorld.isPixelWorld(pixelBlockWorld)) return;
|
if(!PixelBlockWorld.isPixelWorld(pixelBlockWorld)) return;
|
||||||
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(pixelBlockWorld);
|
PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(pixelBlockWorld);
|
||||||
Objects.requireNonNull(pixelBlock);
|
if(pixelBlock == null) return;
|
||||||
pixelBlock.exitBlock(player);
|
pixelBlock.exitBlock(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,18 +38,16 @@ public class PixelBlock {
|
|||||||
private final UUID blockUUID;
|
private final UUID blockUUID;
|
||||||
|
|
||||||
public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
|
public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
|
||||||
|
UUID worldUUID = PixelBlockWorld.getUUIDFromWorld(world);
|
||||||
|
if(worldUUID == null) return null;
|
||||||
return Main.pixelBlocks.stream()
|
return Main.pixelBlocks.stream()
|
||||||
.filter(block -> block.blockUUID.equals(getUUIDFromWorld(world)))
|
.filter(block -> block.blockUUID.equals(worldUUID))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable UUID getUUIDFromWorld(@NotNull World world) {
|
public static boolean exists(@NotNull UUID blockUUID) {
|
||||||
try {
|
return Main.pixelBlocks.stream().anyMatch(pixelBlock -> pixelBlock.blockUUID.equals(blockUUID));
|
||||||
return UUID.fromString(List.of(world.getName().split("/")).getLast());
|
|
||||||
} catch(IllegalArgumentException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable PixelBlock getPixelBlockFromPlacedLocation(@NotNull Location placedLocation) {
|
public static @Nullable PixelBlock getPixelBlockFromPlacedLocation(@NotNull Location placedLocation) {
|
||||||
@@ -76,19 +74,15 @@ public class PixelBlock {
|
|||||||
this.facingDirection = direction;
|
this.facingDirection = direction;
|
||||||
this.lastEntryLocation = lastEntryLocation;
|
this.lastEntryLocation = lastEntryLocation;
|
||||||
|
|
||||||
try {
|
this.pixelWorld = new PixelBlockWorld(this);
|
||||||
this.pixelWorld = new PixelBlockWorld(this);
|
this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
|
||||||
this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
|
this.pixels = new Pixels(this);
|
||||||
this.pixels = new Pixels(this);
|
this.placeholder = new PixelBlockPlaceholder(this);
|
||||||
this.placeholder = new PixelBlockPlaceholder(this);
|
this.hitbox = new PixelBlockHitbox(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));
|
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()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PixelBlock createPixelBlock(UUID blockUUID, UUID ownerUUID, Location pixelBlockLocation, Direction direction) {
|
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) {
|
private PixelBlock(UUID blockUUID, UUID ownerUUID, Location pixelBlockLocation, Direction direction) {
|
||||||
if(Main.pixelBlocks.stream().anyMatch(pixelBlock -> pixelBlock.getBlockUUID().equals(blockUUID)))
|
if(exists(blockUUID))
|
||||||
throw new IllegalStateException(String.format("PixelBlock '%s' ist bereits in der Welt vorhanden!", blockUUID));
|
throw new IllegalStateException(String.format("PixelBlock '%s' already exists in the world!", blockUUID));
|
||||||
|
|
||||||
this.blockUUID = blockUUID;
|
this.blockUUID = blockUUID;
|
||||||
this.ownerUUID = ownerUUID;
|
this.ownerUUID = ownerUUID;
|
||||||
@@ -118,12 +112,8 @@ public class PixelBlock {
|
|||||||
|
|
||||||
this.scheduleEntityUpdate();
|
this.scheduleEntityUpdate();
|
||||||
|
|
||||||
this.getBlockTaskChain()
|
Main.database().savePixelBlock(this);
|
||||||
.async(() -> {
|
Main.pixelBlocks.add(this);
|
||||||
Main.database().savePixelBlock(this);
|
|
||||||
Main.pixelBlocks.add(this);
|
|
||||||
})
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
this.getBlockTaskChain().sync(() -> this.isAccessible = true).execute();
|
this.getBlockTaskChain().sync(() -> this.isAccessible = true).execute();
|
||||||
}
|
}
|
||||||
@@ -139,9 +129,9 @@ public class PixelBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.lastEntryLocation = player.getLocation();
|
this.lastEntryLocation = player.getLocation();
|
||||||
|
Main.database().savePixelBlock(this);
|
||||||
|
|
||||||
getBlockTaskChain()
|
getBlockTaskChain()
|
||||||
.async(() -> Main.database().savePixelBlock(this))
|
|
||||||
.sync(() -> {
|
.sync(() -> {
|
||||||
if(!this.isAccessible) return;
|
if(!this.isAccessible) return;
|
||||||
player.teleport(this.pixelWorld.getSpawnLocation());
|
player.teleport(this.pixelWorld.getSpawnLocation());
|
||||||
@@ -153,7 +143,7 @@ public class PixelBlock {
|
|||||||
|
|
||||||
public void exitBlock(@NotNull Player player) {
|
public void exitBlock(@NotNull Player player) {
|
||||||
this.getBlockTaskChain()
|
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))
|
.sync(() -> this.pixelData = this.pixelWorld.getPixels(this.facingDirection))
|
||||||
.current(() -> Main.logger().info(String.format("%s exited PixelBlock", player.getName())))
|
.current(() -> Main.logger().info(String.format("%s exited PixelBlock", player.getName())))
|
||||||
.delay(1)
|
.delay(1)
|
||||||
@@ -178,16 +168,17 @@ public class PixelBlock {
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy(Player destroyedBy) {
|
public void destroy(Player destroyedBy, boolean force) {
|
||||||
if(!this.isAccessible) return;
|
if(!this.isAccessible) return;
|
||||||
if(Main.configuration().onlyBreakableByOwner() && !destroyedBy.getUniqueId().equals(ownerUUID)) {
|
if(!force && Main.configuration().onlyBreakableByOwner() && !destroyedBy.getUniqueId().equals(ownerUUID)) {
|
||||||
destroyedBy.sendMessage("Dieser Pixelblock gehört nicht dir!");
|
destroyedBy.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Location returnLocation = this.getReturnLocation();
|
||||||
this.pixelWorld.getPlayersInWorld().forEach(p -> {
|
this.pixelWorld.getPlayersInWorld().forEach(p -> {
|
||||||
p.sendMessage(Component.text("Der Pixelblock wurde von einem anderen Spieler abgebaut!", NamedTextColor.RED));
|
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));
|
Main.logger().info(String.format("Destroying PixelBlock '%s' at %s", this.blockUUID, pixelBlockLocation));
|
||||||
@@ -195,20 +186,19 @@ public class PixelBlock {
|
|||||||
|
|
||||||
this.pixelWorld.getEntitiesInWorld().stream()
|
this.pixelWorld.getEntitiesInWorld().stream()
|
||||||
.filter(entity -> entity instanceof Item)
|
.filter(entity -> entity instanceof Item)
|
||||||
.forEach(entity -> entity.teleport(this.lastEntryLocation));
|
.forEach(entity -> entity.teleport(returnLocation));
|
||||||
|
|
||||||
this.getBlockTaskChain()
|
this.getBlockTaskChain()
|
||||||
.sync(() -> {
|
.sync(() -> {
|
||||||
this.removeEntities();
|
this.removeEntities();
|
||||||
World world = this.pixelBlockLocation.getWorld();
|
World world = this.pixelBlockLocation.getWorld();
|
||||||
world.playSound(this.pixelBlockLocation, Sound.BLOCK_COPPER_BULB_BREAK, 1.0F, 30);
|
world.playSound(this.pixelBlockLocation, Sound.BLOCK_COPPER_BULB_BREAK, 1.0F, 2.0F);
|
||||||
world.dropItem(this.pixelBlockLocation.add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
|
world.dropItem(this.getPixelBlockLocation().add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
|
||||||
})
|
|
||||||
.async(() -> {
|
|
||||||
Main.database().deletePixelBlock(this);
|
|
||||||
Main.pixelBlocks.remove(this);
|
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
Main.database().deletePixelBlock(this);
|
||||||
|
Main.pixelBlocks.remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeEntities() {
|
private void removeEntities() {
|
||||||
@@ -243,6 +233,12 @@ public class PixelBlock {
|
|||||||
return this.lastEntryLocation != null;
|
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() {
|
public List<PixelBlockWorld.PixelData> getPixelData() {
|
||||||
return pixelData;
|
return pixelData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
||||||
|
|
||||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||||
|
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
|
||||||
import eu.mhsl.minecraft.pixelblocks.utils.MinMaxUtil;
|
import eu.mhsl.minecraft.pixelblocks.utils.MinMaxUtil;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Interaction;
|
import org.bukkit.entity.Interaction;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class PixelBlockHitbox {
|
public class PixelBlockHitbox {
|
||||||
private static final NamespacedKey hitboxOfTag = new NamespacedKey(Main.plugin(), "hitbox_of");
|
private static final NamespacedKey hitboxOfTag = new NamespacedKey(Main.plugin(), "hitbox_of");
|
||||||
@@ -29,7 +27,7 @@ public class PixelBlockHitbox {
|
|||||||
Interaction interaction;
|
Interaction interaction;
|
||||||
if (pixels.size() <= 5) {
|
if (pixels.size() <= 5) {
|
||||||
interaction = (Interaction) absoluteLocation.getWorld().spawnEntity(
|
interaction = (Interaction) absoluteLocation.getWorld().spawnEntity(
|
||||||
absoluteLocation.clone().add(0.5, -0, 0.5),
|
absoluteLocation.clone().add(0.5, 0, 0.5),
|
||||||
EntityType.INTERACTION
|
EntityType.INTERACTION
|
||||||
);
|
);
|
||||||
interaction.setInteractionHeight(1);
|
interaction.setInteractionHeight(1);
|
||||||
@@ -45,7 +43,7 @@ public class PixelBlockHitbox {
|
|||||||
|
|
||||||
Location spawnLocation = absoluteLocation.clone().add(
|
Location spawnLocation = absoluteLocation.clone().add(
|
||||||
((startingX+endingX)/2+0.5)/pixelsPerBlock,
|
((startingX+endingX)/2+0.5)/pixelsPerBlock,
|
||||||
(startingY/pixelsPerBlock)-0,
|
startingY/pixelsPerBlock,
|
||||||
((startingZ+endingZ)/2+0.5)/pixelsPerBlock
|
((startingZ+endingZ)/2+0.5)/pixelsPerBlock
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -81,19 +79,10 @@ public class PixelBlockHitbox {
|
|||||||
interaction.setInteractionWidth(width);
|
interaction.setInteractionWidth(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
interaction.getPersistentDataContainer()
|
EntityTagUtil.tag(interaction, hitboxOfTag, this.parentBlock.getBlockUUID());
|
||||||
.set(hitboxOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
this.parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1)
|
EntityTagUtil.removeTagged(this.parentBlock.getPixelBlockLocation(), Interaction.class, hitboxOfTag, this.parentBlock.getBlockUUID());
|
||||||
.stream()
|
|
||||||
.filter(interaction -> interaction.getPersistentDataContainer().has(hitboxOfTag))
|
|
||||||
.filter(interaction -> Objects.equals(
|
|
||||||
interaction.getPersistentDataContainer().get(hitboxOfTag, PersistentDataType.STRING),
|
|
||||||
parentBlock.getBlockUUID().toString()
|
|
||||||
))
|
|
||||||
.forEach(Entity::remove);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
||||||
|
|
||||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||||
|
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.ItemDisplay;
|
import org.bukkit.entity.ItemDisplay;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.persistence.PersistentDataHolder;
|
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
import org.bukkit.util.Transformation;
|
import org.bukkit.util.Transformation;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PixelBlockPlaceholder {
|
public class PixelBlockPlaceholder {
|
||||||
@@ -67,20 +64,10 @@ public class PixelBlockPlaceholder {
|
|||||||
displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
|
displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
|
||||||
placeholders.add(displayContainer);
|
placeholders.add(displayContainer);
|
||||||
|
|
||||||
placeholders.stream()
|
placeholders.forEach(placeholder -> EntityTagUtil.tag(placeholder, placeholderOfTag, parentBlockUUID));
|
||||||
.map(PersistentDataHolder::getPersistentDataContainer)
|
|
||||||
.forEach(container -> container.set(placeholderOfTag, PersistentDataType.STRING, parentBlockUUID.toString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
this.parentBlock.getPixelBlockLocation()
|
EntityTagUtil.removeTagged(this.parentBlock.getPixelBlockLocation(), ItemDisplay.class, placeholderOfTag, this.parentBlock.getBlockUUID());
|
||||||
.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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import eu.mhsl.minecraft.pixelblocks.Main;
|
|||||||
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
||||||
import eu.mhsl.minecraft.pixelblocks.utils.LocationUtil;
|
import eu.mhsl.minecraft.pixelblocks.utils.LocationUtil;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.Directional;
|
import org.bukkit.block.data.Directional;
|
||||||
@@ -20,6 +21,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PixelBlockWorld {
|
public class PixelBlockWorld {
|
||||||
private final PixelBlock parentPixelBlock;
|
private final PixelBlock parentPixelBlock;
|
||||||
@@ -28,16 +30,28 @@ public class PixelBlockWorld {
|
|||||||
int worldGrassBorderWidth = 10;
|
int worldGrassBorderWidth = 10;
|
||||||
int pixelsPerBlock = Main.configuration().pixelsPerBlock();
|
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) {
|
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() {
|
public static @Nullable UUID getUUIDFromWorld(@NotNull World world) {
|
||||||
return Bukkit.getWorlds().stream().filter(w -> !PixelBlockWorld.isPixelWorld(w)).toList();
|
if(!isPixelWorld(world)) return null;
|
||||||
}
|
String worldName = world.getName();
|
||||||
|
try {
|
||||||
public static @NotNull List<World> getPixelBlockWorlds() {
|
return UUID.fromString(worldName.substring(worldName.lastIndexOf(File.separatorChar) + 1));
|
||||||
return Bukkit.getWorlds().stream().filter(PixelBlockWorld::isPixelWorld).toList();
|
} catch(IllegalArgumentException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PixelBlockWorld(PixelBlock parentPixelBlock) {
|
public PixelBlockWorld(PixelBlock parentPixelBlock) {
|
||||||
@@ -55,7 +69,7 @@ public class PixelBlockWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String getWorldPathName() {
|
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() {
|
public @NotNull Location getSpawnLocation() {
|
||||||
@@ -78,10 +92,6 @@ public class PixelBlockWorld {
|
|||||||
return new Location(this.world, 0, -60, 0);
|
return new Location(this.world, 0, -60, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Location getBuildOriginEnd() {
|
|
||||||
return getBuildOrigin().add(pixelsPerBlock, pixelsPerBlock, pixelsPerBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull Location getBorderOrigin() {
|
public @NotNull Location getBorderOrigin() {
|
||||||
return getBuildOrigin().subtract(1, 1, 1);
|
return getBuildOrigin().subtract(1, 1, 1);
|
||||||
}
|
}
|
||||||
@@ -99,31 +109,32 @@ public class PixelBlockWorld {
|
|||||||
|
|
||||||
public List<PixelData> getPixels(Direction direction) {
|
public List<PixelData> getPixels(Direction direction) {
|
||||||
List<PixelData> pixelData = new ArrayList<>();
|
List<PixelData> pixelData = new ArrayList<>();
|
||||||
|
Location origin = this.getBuildOrigin();
|
||||||
|
int max = pixelsPerBlock - 1;
|
||||||
|
|
||||||
for(int x = 0; x < pixelsPerBlock; x++) {
|
for(int x = 0; x < pixelsPerBlock; x++) {
|
||||||
for(int y = 0; y < pixelsPerBlock; y++) {
|
for(int y = 0; y < pixelsPerBlock; y++) {
|
||||||
for(int z = 0; z < pixelsPerBlock; z++) {
|
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 Directional directional = blockData instanceof Directional face ? face : null;
|
||||||
@Nullable Rotatable rotatable = blockData instanceof Rotatable rotation ? rotation : null;
|
@Nullable Rotatable rotatable = blockData instanceof Rotatable rotation ? rotation : null;
|
||||||
BlockState state = blockLocation.getBlock().getState();
|
pixelData.add(new PixelData(new Vector(x, y, z), blockData, directional, rotatable, block.getState(), (double) 1 / pixelsPerBlock));
|
||||||
|
|
||||||
if(!blockData.getMaterial().isAir()) {
|
|
||||||
pixelData.add(new PixelData(relativeLocation.toVector(), blockData, directional, rotatable, state, (double) 1 / pixelsPerBlock));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,27 +167,38 @@ public class PixelBlockWorld {
|
|||||||
return world;
|
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() {
|
private void setBuildingPlatform() {
|
||||||
Bukkit.getScheduler().runTask(Main.plugin(), () -> {
|
Bukkit.getScheduler().runTask(Main.plugin(), () -> {
|
||||||
for(int x = 0; x < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; x++) {
|
int platformSize = (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth;
|
||||||
for(int z = 0; z < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; z++) {
|
Location platformOrigin = this.getPlatformOrigin();
|
||||||
getPlatformOrigin().add(x, 0, z).getBlock().setType(Material.GRASS_BLOCK);
|
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);
|
||||||
for(int x = 0; x < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; x++) {
|
platformOrigin.clone().add(x, -1, z).getBlock().setType(Material.DIRT);
|
||||||
for(int z = 0; z < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; z++) {
|
|
||||||
getPlatformOrigin().add(x, -1, z).getBlock().setType(Material.DIRT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < (pixelsPerBlock + 2); x++) {
|
int borderSize = pixelsPerBlock + 2;
|
||||||
for(int z = 0; z < (pixelsPerBlock + 2); z++) {
|
Location borderOrigin = this.getBorderOrigin();
|
||||||
Location currentLocation = getBorderOrigin().add(x, 0, z);
|
for(int x = 0; x < borderSize; x++) {
|
||||||
|
for(int z = 0; z < borderSize; z++) {
|
||||||
if(currentLocation.x() == getBorderOrigin().x() || currentLocation.z() == getBorderOrigin().z()) {
|
if(x == 0 || z == 0 || x == borderSize - 1 || z == borderSize - 1) {
|
||||||
currentLocation.getBlock().setType(Material.RED_CONCRETE);
|
borderOrigin.clone().add(x, 0, z).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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,37 +208,23 @@ public class PixelBlockWorld {
|
|||||||
if(allowPlacements(location)) return;
|
if(allowPlacements(location)) return;
|
||||||
if(!location.clone().subtract(0, 1, 0).getBlock().getType().equals(Material.GRASS_BLOCK)) return;
|
if(!location.clone().subtract(0, 1, 0).getBlock().getType().equals(Material.GRASS_BLOCK)) return;
|
||||||
|
|
||||||
List<Material> flowers = List.of(
|
if(FLOWERS.contains(location.getBlock().getType())) location.getBlock().setType(Material.AIR);
|
||||||
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(!location.getBlock().getType().equals(Material.AIR)) return;
|
if(!location.getBlock().getType().equals(Material.AIR)) return;
|
||||||
|
|
||||||
if(random.nextInt(30) == 0) {
|
if(random.nextInt(30) == 0) {
|
||||||
Material randomFlower = flowers.get(random.nextInt(flowers.size()));
|
location.getBlock().setType(FLOWERS.get(random.nextInt(FLOWERS.size())));
|
||||||
location.getBlock().setType(randomFlower);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Location portalLocation = this.getPortalLocation();
|
||||||
for(int x = 0; x < 4; x++) {
|
for(int x = 0; x < 4; x++) {
|
||||||
for(int y = 0; y < 5; y++) {
|
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 x = 1; x < 3; x++) {
|
||||||
for(int y = 1; y < 4; y++) {
|
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.Main;
|
||||||
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
||||||
|
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
|
||||||
import eu.mhsl.minecraft.pixelblocks.utils.ListUtil;
|
import eu.mhsl.minecraft.pixelblocks.utils.ListUtil;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
@@ -16,7 +17,6 @@ import org.bukkit.block.data.type.EnderChest;
|
|||||||
import org.bukkit.entity.BlockDisplay;
|
import org.bukkit.entity.BlockDisplay;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
import org.bukkit.util.Transformation;
|
import org.bukkit.util.Transformation;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class Pixels {
|
public class Pixels {
|
||||||
private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin(), "pixel_of");
|
private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin(), "pixel_of");
|
||||||
@@ -61,18 +60,16 @@ public class Pixels {
|
|||||||
transform.getTranslation().set(centerOffset.mul(-1));
|
transform.getTranslation().set(centerOffset.mul(-1));
|
||||||
entity.setTransformation(transform);
|
entity.setTransformation(transform);
|
||||||
|
|
||||||
entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
EntityTagUtil.tag(entity, pixelOfTag, this.parentBlock.getBlockUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
List<BlockDisplay> entities = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1)
|
List<BlockDisplay> entities = EntityTagUtil.findTagged(
|
||||||
.stream()
|
this.parentBlock.getPixelBlockLocation(),
|
||||||
.filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag))
|
BlockDisplay.class,
|
||||||
.filter(blockDisplay -> Objects.equals(
|
pixelOfTag,
|
||||||
blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING),
|
this.parentBlock.getBlockUUID()
|
||||||
parentBlock.getBlockUUID().toString()
|
);
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
ListUtil.splitListInParts(10, entities)
|
ListUtil.splitListInParts(10, entities)
|
||||||
.forEach(pixels -> parentBlock.getBlockTaskChain()
|
.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;
|
if(!PixelBlockWorld.isPixelWorld(world)) return;
|
||||||
@Nullable PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(world);
|
@Nullable PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(world);
|
||||||
if(pixelBlock == null) {
|
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);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,20 @@ version: '${version}'
|
|||||||
main: eu.mhsl.minecraft.pixelblocks.Main
|
main: eu.mhsl.minecraft.pixelblocks.Main
|
||||||
api-version: '1.21'
|
api-version: '1.21'
|
||||||
commands:
|
commands:
|
||||||
createpixelblock:
|
pixelblocks:
|
||||||
exitworld:
|
description: Verwaltung von Pixelblöcken
|
||||||
givepixelblock:
|
usage: /pixelblocks <create|give|exit|destroyall>
|
||||||
destroypixelblocks:
|
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