fixed NPE and shutdown issues, cleaned up listeners and build config
Blocks destroyed before ever being entered no longer NPE on the null entry location (new getReturnLocation fallback), destroy no longer mutates the stored block location, placing an item whose block UUID already exists cancels the event with a message instead of eating the item, and pending task chains are flushed on shutdown. Failed block initialization now propagates instead of leaving half-built blocks registered. Listener null checks replaced requireNonNull, listener and method name typos fixed, and the test-server copy path in build.gradle is now a gradle property instead of a hardcoded home directory.
This commit is contained in:
+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 {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.io.File;
|
|||||||
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.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 {
|
||||||
@@ -61,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(),
|
||||||
@@ -91,6 +92,7 @@ public final class Main extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld);
|
Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld);
|
||||||
|
taskFactory.shutdown(5, TimeUnit.SECONDS);
|
||||||
database.close();
|
database.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ public class PixelBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
public static @Nullable PixelBlock getPixelBlockFromPlacedLocation(@NotNull Location placedLocation) {
|
||||||
Location searchLocation = placedLocation.clone().toBlockLocation();
|
Location searchLocation = placedLocation.clone().toBlockLocation();
|
||||||
searchLocation.setPitch(0);
|
searchLocation.setPitch(0);
|
||||||
@@ -76,19 +80,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 +96,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;
|
||||||
@@ -149,7 +149,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)
|
||||||
@@ -181,9 +181,10 @@ public class PixelBlock {
|
|||||||
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));
|
||||||
@@ -191,14 +192,14 @@ 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));
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@@ -238,6 +239,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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user