refactored to not store entities
This commit is contained in:
parent
2810db2e93
commit
c3bf1943a5
@ -1,65 +0,0 @@
|
|||||||
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
|
||||||
|
|
||||||
import eu.mhsl.minecraft.pixelblocks.Main;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.entity.BlockDisplay;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
import org.bukkit.util.Transformation;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class Pixel {
|
|
||||||
private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin, "pixel_of");
|
|
||||||
|
|
||||||
private final @NotNull PixelBlock parentBlock;
|
|
||||||
private final @NotNull BlockDisplay entity;
|
|
||||||
|
|
||||||
private final Location location;
|
|
||||||
|
|
||||||
public static List<Pixel> fromExisting(PixelBlock parentBlock) {
|
|
||||||
return parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1)
|
|
||||||
.stream()
|
|
||||||
.filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag))
|
|
||||||
.filter(blockDisplay -> Objects.equals(
|
|
||||||
blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING),
|
|
||||||
parentBlock.getBlockUUID().toString()
|
|
||||||
))
|
|
||||||
.map(blockDisplay -> new Pixel(parentBlock, blockDisplay))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
private Pixel(@NotNull PixelBlock parentBlock, @NotNull BlockDisplay entity) {
|
|
||||||
this.parentBlock = parentBlock;
|
|
||||||
this.entity = entity;
|
|
||||||
this.location = entity.getLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Pixel newPixel(PixelBlock parentBlock, Vector relativePosition, BlockData blockData, double scale) {
|
|
||||||
return new Pixel(parentBlock, relativePosition, blockData, scale);
|
|
||||||
}
|
|
||||||
private Pixel(@NotNull PixelBlock parentBlock, @NotNull Vector relativePosition, @NotNull BlockData blockData, double scale) {
|
|
||||||
this.parentBlock = parentBlock;
|
|
||||||
this.location = parentBlock.getPixelBlockLocation().add(relativePosition.multiply(scale));
|
|
||||||
this.entity = (BlockDisplay) this.location.getWorld().spawnEntity(this.location, EntityType.BLOCK_DISPLAY);
|
|
||||||
|
|
||||||
this.entity.setBlock(blockData);
|
|
||||||
Transformation transform = this.entity.getTransformation();
|
|
||||||
transform.getScale().set(scale);
|
|
||||||
this.entity.setTransformation(transform);
|
|
||||||
this.entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
this.entity.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location getLocation() {
|
|
||||||
return location.clone();
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,26 +7,21 @@ import eu.mhsl.minecraft.pixelblocks.utils.Direction;
|
|||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.File;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
public class PixelBlock {
|
public class PixelBlock {
|
||||||
private boolean exists = true;
|
private boolean exists = true;
|
||||||
private PixelBlockWorld pixelWorld;
|
private PixelBlockWorld pixelWorld;
|
||||||
|
|
||||||
private final int pixelsPerBlock = Main.configuration.pixelsPerBlock();
|
|
||||||
|
|
||||||
private final Location pixelBlockLocation;
|
private final Location pixelBlockLocation;
|
||||||
private final Direction facingDirection;
|
private final Direction facingDirection;
|
||||||
private List<Pixel> pixels = new ArrayList<>();
|
private Pixels pixels;
|
||||||
|
private List<PixelBlockWorld.PixelData> pixelData;
|
||||||
|
|
||||||
private PixelBlockHitbox hitbox;
|
private PixelBlockHitbox hitbox;
|
||||||
private PixelBlockPlaceholder placeholder;
|
private PixelBlockPlaceholder placeholder;
|
||||||
@ -35,12 +30,6 @@ public class PixelBlock {
|
|||||||
private final UUID ownerUUID;
|
private final UUID ownerUUID;
|
||||||
private final UUID blockUUID;
|
private final UUID blockUUID;
|
||||||
|
|
||||||
public static final int maxPixelsPerBlock = 2000;
|
|
||||||
|
|
||||||
public static @NotNull String getWorldName(@NotNull PixelBlock pixelBlock) {
|
|
||||||
return Main.plugin.getDataFolder().getPath() + File.separator + pixelBlock.blockUUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
|
public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
|
||||||
return Main.pixelBlocks.stream()
|
return Main.pixelBlocks.stream()
|
||||||
.filter(block -> block.blockUUID.equals(getUUIDFromWorld(world)))
|
.filter(block -> block.blockUUID.equals(getUUIDFromWorld(world)))
|
||||||
@ -79,14 +68,14 @@ public class PixelBlock {
|
|||||||
this.facingDirection = direction;
|
this.facingDirection = direction;
|
||||||
this.lastEntryLocation = lastEntryLocation;
|
this.lastEntryLocation = lastEntryLocation;
|
||||||
|
|
||||||
this.ensureChunksLoaded();
|
|
||||||
try {
|
try {
|
||||||
this.pixelWorld = new PixelBlockWorld(this);
|
this.pixelWorld = new PixelBlockWorld(this);
|
||||||
this.pixels = Pixel.fromExisting(this);
|
this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
|
||||||
this.placeholder = PixelBlockPlaceholder.fromExisting(this);
|
this.pixels = new Pixels(this);
|
||||||
this.hitbox = PixelBlockHitbox.fromExisting(this);
|
this.placeholder = new PixelBlockPlaceholder(this);
|
||||||
|
this.hitbox = new PixelBlockHitbox(this);
|
||||||
|
|
||||||
Main.plugin.getLogger().info(String.format("Loaded existing pixelblock '%s' with %d pixels", this.blockUUID, this.pixels.size()));
|
Main.plugin.getLogger().info(String.format("Loaded existing pixelblock '%s'", this.blockUUID));
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Main.plugin.getLogger().info(String.format("Failed initializing existing pixelblock '%s': %s", this.blockUUID, e.getMessage()));
|
Main.plugin.getLogger().info(String.format("Failed initializing existing pixelblock '%s': %s", this.blockUUID, e.getMessage()));
|
||||||
}
|
}
|
||||||
@ -109,8 +98,10 @@ public class PixelBlock {
|
|||||||
this.getBlockTaskChain()
|
this.getBlockTaskChain()
|
||||||
.sync(() -> {
|
.sync(() -> {
|
||||||
this.pixelWorld = new PixelBlockWorld(this);
|
this.pixelWorld = new PixelBlockWorld(this);
|
||||||
this.placeholder = PixelBlockPlaceholder.newPlaceholder(this);
|
this.pixelData = this.pixelWorld.getPixels(this.facingDirection);
|
||||||
this.hitbox = PixelBlockHitbox.newHitbox(this);
|
this.pixels = new Pixels(this);
|
||||||
|
this.placeholder = new PixelBlockPlaceholder(this);
|
||||||
|
this.hitbox = new PixelBlockHitbox(this);
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@ -128,15 +119,6 @@ public class PixelBlock {
|
|||||||
return Main.sharedChain(this.blockUUID.toString());
|
return Main.sharedChain(this.blockUUID.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureChunksLoaded() {
|
|
||||||
Chunk chunk = this.pixelBlockLocation.getChunk();
|
|
||||||
if(!chunk.isLoaded() || !chunk.isEntitiesLoaded()) {
|
|
||||||
Main.plugin.getLogger().info(String.format("Loading chunk '%d, %d' for pixelblock '%s'", chunk.getX(), chunk.getZ(), this.blockUUID));
|
|
||||||
chunk.load(true);
|
|
||||||
chunk.getEntities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enterBlock(@NotNull Player player) {
|
public void enterBlock(@NotNull Player player) {
|
||||||
if(Main.configuration.onlyEditableByOwner() && !player.getUniqueId().equals(ownerUUID)) {
|
if(Main.configuration.onlyEditableByOwner() && !player.getUniqueId().equals(ownerUUID)) {
|
||||||
player.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED));
|
player.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED));
|
||||||
@ -161,68 +143,22 @@ public class PixelBlock {
|
|||||||
this.getBlockTaskChain()
|
this.getBlockTaskChain()
|
||||||
.sync(() -> player.teleport(this.lastEntryLocation != null ? this.lastEntryLocation : this.pixelBlockLocation))
|
.sync(() -> player.teleport(this.lastEntryLocation != null ? this.lastEntryLocation : this.pixelBlockLocation))
|
||||||
.current(() -> Main.plugin.getLogger().info(String.format("%s exited PixelBlock", player.getName())))
|
.current(() -> Main.plugin.getLogger().info(String.format("%s exited PixelBlock", player.getName())))
|
||||||
|
.sync(() -> this.pixelData = this.pixelWorld.getPixels(this.facingDirection))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
this.scheduleEntityUpdate();
|
this.scheduleEntityUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleEntityUpdate() {
|
private void scheduleEntityUpdate() {
|
||||||
record PixelData(PixelBlock parent, Vector relativeLocation, BlockData block, double scale) {
|
|
||||||
Pixel create() {
|
|
||||||
return Pixel.newPixel(this.parent, this.relativeLocation, this.block, this.scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<PixelData> pixelData = new ArrayList<>();
|
|
||||||
|
|
||||||
this.scheduleEntityRemove();
|
|
||||||
this.getBlockTaskChain()
|
this.getBlockTaskChain()
|
||||||
.async(() -> {
|
.sync(this::removeEntities)
|
||||||
for (int x = 0; x < pixelsPerBlock; x++) {
|
.async(() -> Collections.shuffle(this.pixelData))
|
||||||
for (int y = 0; y < pixelsPerBlock; y++) {
|
.delay(1)
|
||||||
for (int z = 0; z < pixelsPerBlock; z++) {
|
.syncLast((pixelData) -> {
|
||||||
World world = pixelBlockLocation.getWorld();
|
this.pixels.spawn();
|
||||||
Location relativeLocation = new Location(world, x, y, z);
|
this.hitbox.spawn();
|
||||||
|
this.placeholder.spawn();
|
||||||
Location blockLocation = this.pixelWorld.getBuildOrigin();
|
|
||||||
switch (this.facingDirection) {
|
|
||||||
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 block = blockLocation.getBlock().getBlockData();
|
|
||||||
|
|
||||||
if(!block.getMaterial().isEmpty()) {
|
|
||||||
pixelData.add(new PixelData(this, relativeLocation.toVector(), block, (double) 1 / pixelsPerBlock));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.async(() -> Collections.shuffle(pixelData))
|
|
||||||
.asyncFirst(() -> {
|
|
||||||
int spawnSpreadInTicks = 10;
|
|
||||||
int chunkSize = (int) Math.ceil((double) pixelData.size() / spawnSpreadInTicks);
|
|
||||||
|
|
||||||
TaskChain<Object> spawnTask = this.getBlockTaskChain();
|
|
||||||
IntStream.range(0, spawnSpreadInTicks)
|
|
||||||
.mapToObj(i -> pixelData.stream()
|
|
||||||
.skip((long) i * chunkSize)
|
|
||||||
.limit(chunkSize)
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.forEach(pixels -> spawnTask
|
|
||||||
.delay(1)
|
|
||||||
.sync(() -> pixels.forEach(pixel -> this.pixels.add(pixel.create()))));
|
|
||||||
|
|
||||||
return spawnTask;
|
|
||||||
})
|
|
||||||
.syncLast((chain) -> chain
|
|
||||||
.sync(() -> {
|
|
||||||
this.hitbox = PixelBlockHitbox.newHitbox(this);
|
|
||||||
this.placeholder = PixelBlockPlaceholder.newPlaceholder(this);
|
|
||||||
Main.plugin.getLogger().info(String.format("Placed %d entities for PixelBlock '%s'", this.pixels.size(), this.blockUUID));
|
|
||||||
})
|
|
||||||
.execute())
|
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,9 +197,9 @@ public class PixelBlock {
|
|||||||
.filter(entity -> entity instanceof Item)
|
.filter(entity -> entity instanceof Item)
|
||||||
.forEach(entity -> entity.teleport(this.lastEntryLocation));
|
.forEach(entity -> entity.teleport(this.lastEntryLocation));
|
||||||
|
|
||||||
this.scheduleEntityRemove();
|
|
||||||
this.getBlockTaskChain()
|
this.getBlockTaskChain()
|
||||||
.sync(() -> {
|
.sync(() -> {
|
||||||
|
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, 30);
|
||||||
world.dropItem(this.pixelBlockLocation.add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
|
world.dropItem(this.pixelBlockLocation.add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this));
|
||||||
@ -275,25 +211,10 @@ public class PixelBlock {
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleEntityRemove() {
|
private void removeEntities() {
|
||||||
this.getBlockTaskChain()
|
this.pixels.destroy();
|
||||||
.current(() -> Main.plugin.getLogger()
|
this.placeholder.destroy();
|
||||||
.info(String.format("Removing %d pixels in PixelBlock '%s'", this.pixels.size(), this.blockUUID)))
|
this.hitbox.destroy();
|
||||||
.sync(this::ensureChunksLoaded)
|
|
||||||
.delay(1)
|
|
||||||
.sync(() -> {
|
|
||||||
List<Entity> entitiesBefore = this.pixelBlockLocation.getWorld().getEntities();
|
|
||||||
this.pixels.forEach(Pixel::destroy);
|
|
||||||
List<Entity> entitiesAfter = this.pixelBlockLocation.getWorld().getEntities();
|
|
||||||
|
|
||||||
Main.plugin.getLogger().info("Entities im Chunk vor dem Entfernen: " + entitiesBefore.size());
|
|
||||||
Main.plugin.getLogger().info("Entities im Chunk nach dem Entfernen: " + entitiesAfter.size());
|
|
||||||
|
|
||||||
this.pixels.clear();
|
|
||||||
this.placeholder.destroy();
|
|
||||||
this.hitbox.destroy();
|
|
||||||
})
|
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull PixelBlockWorld getPixelWorld() {
|
public @NotNull PixelBlockWorld getPixelWorld() {
|
||||||
@ -312,8 +233,8 @@ public class PixelBlock {
|
|||||||
return this.lastEntryLocation != null;
|
return this.lastEntryLocation != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pixel> getPixels() {
|
public List<PixelBlockWorld.PixelData> getPixelData() {
|
||||||
return pixels;
|
return pixelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Location getLastEntryLocation() {
|
public Location getLastEntryLocation() {
|
||||||
|
@ -1,24 +1,94 @@
|
|||||||
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.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 org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
private final Interaction interaction;
|
private final PixelBlock parentBlock;
|
||||||
|
|
||||||
public static PixelBlockHitbox fromExisting(PixelBlock parentBlock) {
|
public PixelBlockHitbox(PixelBlock parentBlock) {
|
||||||
Interaction hitBox = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1)
|
this.parentBlock = parentBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawn() {
|
||||||
|
Location pixelBlockLocation = this.parentBlock.getPixelBlockLocation();
|
||||||
|
List<PixelBlockWorld.PixelData> pixels = this.parentBlock.getPixelData();
|
||||||
|
double scale = pixels.getFirst().scale();
|
||||||
|
|
||||||
|
float offset = (float) Main.configuration.hitboxOffset();
|
||||||
|
int pixelsPerBlock = Main.configuration.pixelsPerBlock();
|
||||||
|
|
||||||
|
Interaction interaction;
|
||||||
|
if(true) {
|
||||||
|
interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
|
||||||
|
pixelBlockLocation.clone().add(0.5, -offset, 0.5),
|
||||||
|
EntityType.INTERACTION
|
||||||
|
);
|
||||||
|
interaction.setInteractionHeight(1 + 2*offset);
|
||||||
|
interaction.setInteractionWidth(1 + 2*offset);
|
||||||
|
} else {
|
||||||
|
// double startingX = this.parentBlock.getPixelBlockLocation().x() + MinMaxUtil.getMinProperty(pixels, pixel -> pixel.relativeLocation().getX()) * scale;
|
||||||
|
// double startingY = this.parentBlock.getPixelBlockLocation().y() + MinMaxUtil.getMinProperty(pixels, pixel -> pixel.relativeLocation().getY()) * scale;
|
||||||
|
// double startingZ = this.parentBlock.getPixelBlockLocation().z() + MinMaxUtil.getMinProperty(pixels, pixel -> pixel.relativeLocation().getZ()) * scale;
|
||||||
|
//
|
||||||
|
// double endingX = this.parentBlock.getPixelBlockLocation().x() + MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.relativeLocation().getX()) * scale;
|
||||||
|
// double endingY = this.parentBlock.getPixelBlockLocation().y() + MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.relativeLocation().getY()) * scale;
|
||||||
|
// double endingZ = this.parentBlock.getPixelBlockLocation().z() + MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.relativeLocation().getZ()) * scale;
|
||||||
|
//
|
||||||
|
// Location spawnLocation = pixelBlockLocation.clone().add(
|
||||||
|
// ((startingX+endingX+1)/2)/pixelsPerBlock,
|
||||||
|
// (startingY/pixelsPerBlock)-offset,
|
||||||
|
// ((startingZ+endingZ+1)/2)/pixelsPerBlock
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// float height = (float) (endingY-startingY+1)/pixelsPerBlock + 2*offset;
|
||||||
|
//
|
||||||
|
// float width;
|
||||||
|
// if((endingX-startingX) > (endingZ-startingZ)) {
|
||||||
|
// width = (float) (endingX-startingX+1)/pixelsPerBlock + 2*offset;
|
||||||
|
// } else {
|
||||||
|
// width = (float) (endingZ-startingZ+1)/pixelsPerBlock + 2*offset;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if(spawnLocation.getX()+width/2 > pixelBlockLocation.getX()+1) {
|
||||||
|
// spawnLocation.subtract((spawnLocation.getX()+width/2)-(pixelBlockLocation.getX()+1), 0, 0);
|
||||||
|
// }
|
||||||
|
// if(spawnLocation.getX()-width/2 < pixelBlockLocation.getX()) {
|
||||||
|
// spawnLocation.add(pixelBlockLocation.getX()-(spawnLocation.getX()-width/2), 0, 0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if(spawnLocation.getZ()+width/2 > pixelBlockLocation.getZ()+1) {
|
||||||
|
// spawnLocation.subtract(0, 0, (spawnLocation.getZ()+width/2)-(pixelBlockLocation.getZ()+1));
|
||||||
|
// }
|
||||||
|
// if(spawnLocation.getZ()-width/2 < pixelBlockLocation.getZ()) {
|
||||||
|
// spawnLocation.add(0, 0, pixelBlockLocation.getZ()-(spawnLocation.getZ()-width/2));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
|
||||||
|
// spawnLocation,
|
||||||
|
// EntityType.INTERACTION
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// interaction.setInteractionHeight(height);
|
||||||
|
// interaction.setInteractionWidth(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
interaction.getPersistentDataContainer()
|
||||||
|
.set(hitboxOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
this.parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(interaction -> interaction.getPersistentDataContainer().has(hitboxOfTag))
|
.filter(interaction -> interaction.getPersistentDataContainer().has(hitboxOfTag))
|
||||||
.filter(interaction -> Objects.equals(
|
.filter(interaction -> Objects.equals(
|
||||||
@ -28,81 +98,6 @@ public class PixelBlockHitbox {
|
|||||||
.reduce((a, b) -> {
|
.reduce((a, b) -> {
|
||||||
throw new IllegalStateException(String.format("Mehrere hitboxen für PixelBlock '%s' gefunden!", parentBlock.getBlockUUID()));
|
throw new IllegalStateException(String.format("Mehrere hitboxen für PixelBlock '%s' gefunden!", parentBlock.getBlockUUID()));
|
||||||
})
|
})
|
||||||
.orElseThrow();
|
.ifPresent(Entity::remove);
|
||||||
|
|
||||||
Main.plugin.getLogger().info(String.format("Found existing hitbox '%s' for block '%s'", hitBox.getUniqueId(), parentBlock.getBlockUUID()));
|
|
||||||
return new PixelBlockHitbox(hitBox);
|
|
||||||
}
|
|
||||||
private PixelBlockHitbox(Interaction interaction) {
|
|
||||||
this.interaction = interaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PixelBlockHitbox newHitbox(PixelBlock parentBlock) {
|
|
||||||
return new PixelBlockHitbox(parentBlock.getPixelBlockLocation(), parentBlock.getPixels(), parentBlock.getBlockUUID());
|
|
||||||
}
|
|
||||||
private PixelBlockHitbox(Location pixelBlockLocation, List<Pixel> pixels, UUID parentBlockUUID) {
|
|
||||||
float offset = (float) Main.configuration.hitboxOffset();
|
|
||||||
int pixelsPerBlock = Main.configuration.pixelsPerBlock();
|
|
||||||
|
|
||||||
if(pixels.size() > 5 || true) {
|
|
||||||
interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
|
|
||||||
pixelBlockLocation.clone().add(0.5, -offset, 0.5),
|
|
||||||
EntityType.INTERACTION
|
|
||||||
);
|
|
||||||
interaction.setInteractionHeight(1 + 2*offset);
|
|
||||||
interaction.setInteractionWidth(1 + 2*offset);
|
|
||||||
} else {
|
|
||||||
double startingX = MinMaxUtil.getMinProperty(pixels, pixel -> pixel.getLocation().getX());
|
|
||||||
double startingY = MinMaxUtil.getMinProperty(pixels, pixel -> pixel.getLocation().getY());
|
|
||||||
double startingZ = MinMaxUtil.getMinProperty(pixels, pixel -> pixel.getLocation().getZ());
|
|
||||||
|
|
||||||
double endingX = MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.getLocation().getX());
|
|
||||||
double endingY = MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.getLocation().getY());
|
|
||||||
double endingZ = MinMaxUtil.getMaxProperty(pixels, pixel -> pixel.getLocation().getZ());
|
|
||||||
|
|
||||||
Location spawnLocation = pixelBlockLocation.clone().add(
|
|
||||||
((startingX+endingX+1)/2)/pixelsPerBlock,
|
|
||||||
(startingY/pixelsPerBlock)-offset,
|
|
||||||
((startingZ+endingZ+1)/2)/pixelsPerBlock
|
|
||||||
);
|
|
||||||
|
|
||||||
float height = (float) (endingY-startingY+1)/pixelsPerBlock + 2*offset;
|
|
||||||
|
|
||||||
float width;
|
|
||||||
if((endingX-startingX) > (endingZ-startingZ)) {
|
|
||||||
width = (float) (endingX-startingX+1)/pixelsPerBlock + 2*offset;
|
|
||||||
} else {
|
|
||||||
width = (float) (endingZ-startingZ+1)/pixelsPerBlock + 2*offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spawnLocation.getX()+width/2 > pixelBlockLocation.getX()+1) {
|
|
||||||
spawnLocation.subtract((spawnLocation.getX()+width/2)-(pixelBlockLocation.getX()+1), 0, 0);
|
|
||||||
}
|
|
||||||
if(spawnLocation.getX()-width/2 < pixelBlockLocation.getX()) {
|
|
||||||
spawnLocation.add(pixelBlockLocation.getX()-(spawnLocation.getX()-width/2), 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spawnLocation.getZ()+width/2 > pixelBlockLocation.getZ()+1) {
|
|
||||||
spawnLocation.subtract(0, 0, (spawnLocation.getZ()+width/2)-(pixelBlockLocation.getZ()+1));
|
|
||||||
}
|
|
||||||
if(spawnLocation.getZ()-width/2 < pixelBlockLocation.getZ()) {
|
|
||||||
spawnLocation.add(0, 0, pixelBlockLocation.getZ()-(spawnLocation.getZ()-width/2));
|
|
||||||
}
|
|
||||||
|
|
||||||
interaction = (Interaction) pixelBlockLocation.getWorld().spawnEntity(
|
|
||||||
spawnLocation,
|
|
||||||
EntityType.INTERACTION
|
|
||||||
);
|
|
||||||
|
|
||||||
interaction.setInteractionHeight(height);
|
|
||||||
interaction.setInteractionWidth(width);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.interaction.getPersistentDataContainer()
|
|
||||||
.set(hitboxOfTag, PersistentDataType.STRING, parentBlockUUID.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
this.interaction.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,32 +18,16 @@ import java.util.*;
|
|||||||
public class PixelBlockPlaceholder {
|
public class PixelBlockPlaceholder {
|
||||||
private static final NamespacedKey placeholderOfTag = new NamespacedKey(Main.plugin, "placeholder_of");
|
private static final NamespacedKey placeholderOfTag = new NamespacedKey(Main.plugin, "placeholder_of");
|
||||||
|
|
||||||
List<ItemDisplay> placeholders = new ArrayList<>();
|
private final PixelBlock parentBlock;
|
||||||
|
|
||||||
public static PixelBlockPlaceholder fromExisting(PixelBlock parentBlock) {
|
public PixelBlockPlaceholder(PixelBlock parentBlock) {
|
||||||
List<ItemDisplay> placeholders = parentBlock.getPixelBlockLocation()
|
this.parentBlock = parentBlock;
|
||||||
.getNearbyEntitiesByType(ItemDisplay.class, 1)
|
|
||||||
.stream()
|
|
||||||
.filter(itemDisplay -> itemDisplay.getPersistentDataContainer().has(placeholderOfTag))
|
|
||||||
.filter(itemDisplay -> Objects.equals(
|
|
||||||
itemDisplay.getPersistentDataContainer().get(placeholderOfTag, PersistentDataType.STRING),
|
|
||||||
parentBlock.getBlockUUID().toString()
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
Main.plugin.getLogger().info(String.format("Found %d existing placeholders for block '%s'", placeholders.size(), parentBlock.getBlockUUID()));
|
|
||||||
return new PixelBlockPlaceholder(placeholders);
|
|
||||||
}
|
|
||||||
private PixelBlockPlaceholder(List<ItemDisplay> itemDisplays) {
|
|
||||||
this.placeholders = itemDisplays;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PixelBlockPlaceholder newPlaceholder(PixelBlock parentBlock) {
|
public void spawn() {
|
||||||
return new PixelBlockPlaceholder(parentBlock);
|
if(parentBlock.getPixelData().size() > 5) return;
|
||||||
}
|
|
||||||
private PixelBlockPlaceholder(PixelBlock parentBlock) {
|
|
||||||
if(parentBlock.getPixels().size() > 5) return;
|
|
||||||
|
|
||||||
|
List<ItemDisplay> placeholders = new ArrayList<>();
|
||||||
Location pixelBlockLocation = parentBlock.getPixelBlockLocation();
|
Location pixelBlockLocation = parentBlock.getPixelBlockLocation();
|
||||||
UUID parentBlockUUID = parentBlock.getBlockUUID();
|
UUID parentBlockUUID = parentBlock.getBlockUUID();
|
||||||
|
|
||||||
@ -56,7 +40,7 @@ public class PixelBlockPlaceholder {
|
|||||||
EntityType.ITEM_DISPLAY
|
EntityType.ITEM_DISPLAY
|
||||||
);
|
);
|
||||||
verticalCore.setRotation(i, 0);
|
verticalCore.setRotation(i, 0);
|
||||||
this.placeholders.add(verticalCore);
|
placeholders.add(verticalCore);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemDisplay horizontalCore = (ItemDisplay) pixelBlockWorld.spawnEntity(
|
ItemDisplay horizontalCore = (ItemDisplay) pixelBlockWorld.spawnEntity(
|
||||||
@ -64,9 +48,9 @@ public class PixelBlockPlaceholder {
|
|||||||
EntityType.ITEM_DISPLAY
|
EntityType.ITEM_DISPLAY
|
||||||
);
|
);
|
||||||
horizontalCore.setRotation(0, 90);
|
horizontalCore.setRotation(0, 90);
|
||||||
this.placeholders.add(horizontalCore);
|
placeholders.add(horizontalCore);
|
||||||
|
|
||||||
this.placeholders.forEach(coreDisplay -> {
|
placeholders.forEach(coreDisplay -> {
|
||||||
coreDisplay.setItemStack(ItemStack.of(Material.END_CRYSTAL));
|
coreDisplay.setItemStack(ItemStack.of(Material.END_CRYSTAL));
|
||||||
Transformation transform = coreDisplay.getTransformation();
|
Transformation transform = coreDisplay.getTransformation();
|
||||||
transform.getScale().set(0.5);
|
transform.getScale().set(0.5);
|
||||||
@ -78,18 +62,22 @@ public class PixelBlockPlaceholder {
|
|||||||
EntityType.ITEM_DISPLAY
|
EntityType.ITEM_DISPLAY
|
||||||
);
|
);
|
||||||
displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
|
displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
|
||||||
this.placeholders.add(displayContainer);
|
placeholders.add(displayContainer);
|
||||||
|
|
||||||
this.setDataTags(parentBlockUUID);
|
placeholders.stream()
|
||||||
}
|
|
||||||
|
|
||||||
private void setDataTags(UUID parentBlockUUID) {
|
|
||||||
this.placeholders.stream()
|
|
||||||
.map(PersistentDataHolder::getPersistentDataContainer)
|
.map(PersistentDataHolder::getPersistentDataContainer)
|
||||||
.forEach(container -> container.set(placeholderOfTag, PersistentDataType.STRING, parentBlockUUID.toString()));
|
.forEach(container -> container.set(placeholderOfTag, PersistentDataType.STRING, parentBlockUUID.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
this.placeholders.forEach(Entity::remove);
|
this.parentBlock.getPixelBlockLocation()
|
||||||
|
.getNearbyEntitiesByType(ItemDisplay.class, 1)
|
||||||
|
.stream()
|
||||||
|
.filter(itemDisplay -> itemDisplay.getPersistentDataContainer().has(placeholderOfTag))
|
||||||
|
.filter(itemDisplay -> Objects.equals(
|
||||||
|
itemDisplay.getPersistentDataContainer().get(placeholderOfTag, PersistentDataType.STRING),
|
||||||
|
parentBlock.getBlockUUID().toString()
|
||||||
|
))
|
||||||
|
.forEach(Entity::remove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +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.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.data.BlockData;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
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;
|
||||||
@ -17,7 +21,7 @@ import static eu.mhsl.minecraft.pixelblocks.Main.plugin;
|
|||||||
|
|
||||||
public class PixelBlockWorld {
|
public class PixelBlockWorld {
|
||||||
private final PixelBlock parentPixelBlock;
|
private final PixelBlock parentPixelBlock;
|
||||||
private World world;
|
private final World world;
|
||||||
|
|
||||||
int worldGrassBorderWidth = 10;
|
int worldGrassBorderWidth = 10;
|
||||||
int pixelsPerBlock = Main.configuration.pixelsPerBlock();
|
int pixelsPerBlock = Main.configuration.pixelsPerBlock();
|
||||||
@ -88,6 +92,34 @@ public class PixelBlockWorld {
|
|||||||
return getBorderOrigin().add(worldGrassBorderWidth + pixelsPerBlock, 0, worldGrassBorderWidth + pixelsPerBlock);
|
return getBorderOrigin().add(worldGrassBorderWidth + pixelsPerBlock, 0, worldGrassBorderWidth + pixelsPerBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record PixelData(Vector relativeLocation, BlockData block, double scale) {}
|
||||||
|
public List<PixelData> getPixels(Direction direction) {
|
||||||
|
List<PixelData> pixelData = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int x = 0; x < pixelsPerBlock; x++) {
|
||||||
|
for (int y = 0; y < pixelsPerBlock; y++) {
|
||||||
|
for (int z = 0; z < pixelsPerBlock; z++) {
|
||||||
|
Location relativeLocation = new Location(world, x, y, z);
|
||||||
|
|
||||||
|
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 block = blockLocation.getBlock().getBlockData();
|
||||||
|
|
||||||
|
if(!block.getMaterial().isEmpty()) {
|
||||||
|
pixelData.add(new PixelData(relativeLocation.toVector(), block, (double) 1 / pixelsPerBlock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pixelData;
|
||||||
|
}
|
||||||
|
|
||||||
private World loadOrCreatePixelWorld() {
|
private World loadOrCreatePixelWorld() {
|
||||||
final WorldCreator worldCreator = new WorldCreator(getWorldPathName());
|
final WorldCreator worldCreator = new WorldCreator(getWorldPathName());
|
||||||
|
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package eu.mhsl.minecraft.pixelblocks.pixelblock;
|
||||||
|
|
||||||
|
import eu.mhsl.minecraft.pixelblocks.Main;
|
||||||
|
import eu.mhsl.minecraft.pixelblocks.utils.ListUtil;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.entity.BlockDisplay;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.bukkit.util.Transformation;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Pixels {
|
||||||
|
private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin, "pixel_of");
|
||||||
|
|
||||||
|
private final @NotNull PixelBlock parentBlock;
|
||||||
|
|
||||||
|
public Pixels(@NotNull PixelBlock parentBlock) {
|
||||||
|
this.parentBlock = parentBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawn() {
|
||||||
|
ListUtil.splitListInParts(10, this.parentBlock.getPixelData())
|
||||||
|
.forEach(pixels -> parentBlock.getBlockTaskChain()
|
||||||
|
.delay(1)
|
||||||
|
.sync(() -> pixels.forEach(this::spawnPixel))
|
||||||
|
.execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnPixel(PixelBlockWorld.PixelData pixelData) {
|
||||||
|
Location pixelBlockLocation = this.parentBlock.getPixelBlockLocation();
|
||||||
|
Location pixelLocation = pixelBlockLocation.add(pixelData.relativeLocation().multiply(pixelData.scale()));
|
||||||
|
BlockDisplay entity = (BlockDisplay) pixelBlockLocation.getWorld().spawnEntity(pixelLocation, EntityType.BLOCK_DISPLAY);
|
||||||
|
|
||||||
|
entity.setBlock(pixelData.block());
|
||||||
|
Transformation transform = entity.getTransformation();
|
||||||
|
transform.getScale().set(pixelData.scale());
|
||||||
|
entity.setTransformation(transform);
|
||||||
|
entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
List<BlockDisplay> entities = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1)
|
||||||
|
.stream()
|
||||||
|
.filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag))
|
||||||
|
.filter(blockDisplay -> Objects.equals(
|
||||||
|
blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING),
|
||||||
|
parentBlock.getBlockUUID().toString()
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
ListUtil.splitListInParts(10, entities)
|
||||||
|
.forEach(pixels -> parentBlock.getBlockTaskChain()
|
||||||
|
.delay(1)
|
||||||
|
.sync(() -> pixels.forEach(Entity::remove))
|
||||||
|
.execute());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package eu.mhsl.minecraft.pixelblocks.utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class ListUtil {
|
||||||
|
public static <T> List<List<T>> splitListInParts(int parts, List<T> list) {
|
||||||
|
int actualParts = Math.min(parts, list.size());
|
||||||
|
int chunkSize = (int) Math.ceil((double) list.size() / actualParts);
|
||||||
|
return IntStream.range(0, actualParts)
|
||||||
|
.mapToObj(i -> list.stream()
|
||||||
|
.skip((long) i * chunkSize)
|
||||||
|
.limit(chunkSize)
|
||||||
|
.collect(Collectors.toList()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user