geforkt von Mirrors/AxiomPaperPlugin
Preliminary PlotSquared support for SetBlockBuffer packet
Dieser Commit ist enthalten in:
Ursprung
ca7ef8266d
Commit
e5c8acff02
68
src/main/java/com/moulberry/axiom/integration/Box.java
Normale Datei
68
src/main/java/com/moulberry/axiom/integration/Box.java
Normale Datei
@ -0,0 +1,68 @@
|
||||
package com.moulberry.axiom.integration;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public record Box(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
||||
|
||||
@Nullable
|
||||
public Box tryCombine(Box other) {
|
||||
if (this.completelyOverlaps(other)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (other.completelyOverlaps(this)) {
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.minX == this.minX && other.maxX == this.maxX) {
|
||||
if (other.minY == this.minY && other.maxY == this.maxY) {
|
||||
if (areLineSegmentsContinuous(other.minZ, other.maxZ, this.minZ, this.maxZ)) {
|
||||
return new Box(
|
||||
other.minX, other.minY, Math.min(other.minZ, this.minZ),
|
||||
other.maxX, other.maxY, Math.max(other.maxZ, this.maxZ)
|
||||
);
|
||||
}
|
||||
} else if (other.minZ == this.minZ && other.maxZ == this.maxZ) {
|
||||
if (areLineSegmentsContinuous(other.minY, other.maxY, this.minY, this.maxY)) {
|
||||
return new Box(
|
||||
other.minX, Math.min(other.minY, this.minY), other.minZ,
|
||||
other.maxX, Math.max(other.maxY, this.maxY), other.maxZ
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (other.minY == this.minY && other.maxY == this.maxY &&
|
||||
other.minZ == this.minZ && other.maxZ == this.maxZ) {
|
||||
if (areLineSegmentsContinuous(other.minX, other.maxX, this.minX, this.maxX)) {
|
||||
return new Box(
|
||||
Math.min(other.minX, this.minX), other.minY, other.minZ,
|
||||
Math.max(other.maxX, this.maxX), other.maxY, other.maxZ
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null; // Not able to combine
|
||||
}
|
||||
|
||||
public boolean completelyOverlaps(Box other) {
|
||||
return this.minX() <= other.minX() && this.minY() <= other.minY() && this.minZ() <= other.minZ() &&
|
||||
this.maxX() >= other.maxX() && this.maxY() >= other.maxY() && this.maxZ() >= other.maxZ();
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y, int z) {
|
||||
return this.minX() <= x && this.minY() <= y && this.minZ() <= z &&
|
||||
this.maxX() >= x && this.maxY() >= y && this.maxZ() >= z;
|
||||
}
|
||||
|
||||
private static boolean areLineSegmentsContinuous(int min1, int max1, int min2, int max2) {
|
||||
int size1 = max1 - min1 + 1;
|
||||
int size2 = max2 - min2 + 1;
|
||||
|
||||
float mid1 = (min1 + max1);
|
||||
float mid2 = (min2 + max2);
|
||||
|
||||
float midDiff = Math.abs(mid1 - mid2);
|
||||
return midDiff <= size1 + size2;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
package com.moulberry.axiom.integration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SectionPermissionChecker {
|
||||
|
||||
boolean allAllowed();
|
||||
boolean noneAllowed();
|
||||
boolean allowed(int x, int y, int z);
|
||||
Box bounds();
|
||||
|
||||
static SectionPermissionChecker fromAllowedBoxes(List<Box> allowed) {
|
||||
if (allowed.isEmpty()) return NONE_ALLOWED;
|
||||
|
||||
if (allowed.size() == 1) {
|
||||
Box allowedBox = allowed.get(0);
|
||||
if (allowedBox.completelyOverlaps(FULL_BOUNDS)) {
|
||||
return ALL_ALLOWED;
|
||||
} else {
|
||||
return new AllAllowedInBox(allowedBox);
|
||||
}
|
||||
}
|
||||
|
||||
int minBoundsX = 15;
|
||||
int minBoundsY = 15;
|
||||
int minBoundsZ = 15;
|
||||
int maxBoundsX = 0;
|
||||
int maxBoundsY = 0;
|
||||
int maxBoundsZ = 0;
|
||||
|
||||
for (Box box : allowed) {
|
||||
minBoundsX = Math.min(box.minX(), minBoundsX);
|
||||
minBoundsY = Math.min(box.minY(), minBoundsY);
|
||||
minBoundsZ = Math.min(box.minZ(), minBoundsZ);
|
||||
maxBoundsX = Math.max(box.maxX(), maxBoundsX);
|
||||
maxBoundsY = Math.max(box.maxY(), maxBoundsY);
|
||||
maxBoundsZ = Math.max(box.maxZ(), maxBoundsZ);
|
||||
}
|
||||
|
||||
return new AllAllowedBoxes(new Box(minBoundsX, minBoundsY, minBoundsZ, maxBoundsX, maxBoundsY, maxBoundsZ), allowed);
|
||||
}
|
||||
|
||||
record AllAllowedInBox(Box box) implements SectionPermissionChecker {
|
||||
@Override
|
||||
public boolean allAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noneAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowed(int x, int y, int z) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Box bounds() {
|
||||
return box;
|
||||
}
|
||||
}
|
||||
|
||||
record AllAllowedBoxes(Box bounds, List<Box> allowed) implements SectionPermissionChecker {
|
||||
@Override
|
||||
public boolean allAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noneAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowed(int x, int y, int z) {
|
||||
for (Box box : this.allowed) {
|
||||
if (box.contains(x, y, z)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Box bounds() {
|
||||
return this.bounds;
|
||||
}
|
||||
}
|
||||
|
||||
Box FULL_BOUNDS = new Box(0, 0, 0, 15, 15, 15);
|
||||
SectionPermissionChecker ALL_ALLOWED = new SectionPermissionChecker() {
|
||||
@Override
|
||||
public boolean allAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noneAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowed(int x, int y, int z) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Box bounds() {
|
||||
return FULL_BOUNDS;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Box EMPTY_BOUNDS = new Box(0, 0, 0, 0, 0, 0);
|
||||
SectionPermissionChecker NONE_ALLOWED = new SectionPermissionChecker() {
|
||||
@Override
|
||||
public boolean allAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noneAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowed(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Box bounds() {
|
||||
return EMPTY_BOUNDS;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.moulberry.axiom.integration.plotsquared;
|
||||
|
||||
|
||||
import com.moulberry.axiom.integration.SectionPermissionChecker;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
@ -30,4 +31,11 @@ public class PlotSquaredIntegration {
|
||||
return PlotSquaredIntegrationImpl.isPlotWorld(world);
|
||||
}
|
||||
|
||||
public static SectionPermissionChecker checkSection(Player player, World world, int sectionX, int sectionY, int sectionZ) {
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PlotSquared")) {
|
||||
return SectionPermissionChecker.ALL_ALLOWED;
|
||||
}
|
||||
return PlotSquaredIntegrationImpl.checkSection(player, world, sectionX, sectionY, sectionZ);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.moulberry.axiom.integration.plotsquared;
|
||||
|
||||
import com.moulberry.axiom.integration.Box;
|
||||
import com.moulberry.axiom.integration.SectionPermissionChecker;
|
||||
import com.plotsquared.bukkit.player.BukkitPlayer;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
@ -8,17 +10,20 @@ import com.plotsquared.core.location.Location;
|
||||
import com.plotsquared.core.permissions.Permission;
|
||||
import com.plotsquared.core.plot.Plot;
|
||||
import com.plotsquared.core.plot.PlotArea;
|
||||
import com.plotsquared.core.plot.PlotId;
|
||||
import com.plotsquared.core.plot.flag.implementations.BreakFlag;
|
||||
import com.plotsquared.core.plot.flag.implementations.DoneFlag;
|
||||
import com.plotsquared.core.plot.flag.types.BlockTypeWrapper;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* PlotSquared, a land and world management plugin for Minecraft.
|
||||
@ -117,6 +122,7 @@ public class PlotSquaredIntegrationImpl {
|
||||
}
|
||||
|
||||
private static final WeakHashMap<World, Boolean> plotWorldCache = new WeakHashMap<>();
|
||||
|
||||
static boolean isPlotWorld(World world) {
|
||||
if (plotWorldCache.containsKey(world)) {
|
||||
return plotWorldCache.get(world);
|
||||
@ -134,7 +140,85 @@ public class PlotSquaredIntegrationImpl {
|
||||
|
||||
plotWorldCache.put(world, isPlotWorld);
|
||||
return isPlotWorld;
|
||||
|
||||
}
|
||||
|
||||
static SectionPermissionChecker checkSection(Player player, World world, int sectionX, int sectionY, int sectionZ) {
|
||||
int minX = sectionX * 16;
|
||||
int minY = sectionY * 16;
|
||||
int minZ = sectionZ * 16;
|
||||
int maxX = sectionX * 16 + 15;
|
||||
int maxY = sectionY * 16 + 15;
|
||||
int maxZ = sectionZ * 16 + 15;
|
||||
|
||||
PlotArea[] plotAreas = PlotSquared.get().getPlotAreaManager().getPlotAreas(world.getName(), new CuboidRegion(
|
||||
BlockVector3.at(minX, minY, minZ),
|
||||
BlockVector3.at(maxX, maxY, maxZ)
|
||||
));
|
||||
|
||||
if (plotAreas.length == 0) {
|
||||
return SectionPermissionChecker.ALL_ALLOWED;
|
||||
}
|
||||
|
||||
Set<Plot> checkedPlots = new HashSet<>();
|
||||
List<Box> allowed = new ArrayList<>();
|
||||
|
||||
for (PlotArea plotArea : plotAreas) {
|
||||
for (int px = minX; px <= maxX; px += 15) {
|
||||
for (int py = minY; py <= maxY; py += 15) {
|
||||
for (int pz = minZ; pz <= maxZ; pz += 15) {
|
||||
PlotId pid = plotArea.getPlotManager().getPlotId(px, py, pz);
|
||||
if (pid == null) continue;
|
||||
Plot plot = plotArea.getOwnedPlotAbs(pid);
|
||||
if (plot == null) continue;
|
||||
|
||||
if (!checkedPlots.add(plot)) continue;
|
||||
|
||||
if (!plot.hasOwner()) continue;
|
||||
if (!plot.isAdded(player.getUniqueId())) continue;
|
||||
if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) continue;
|
||||
|
||||
Location bottom = plot.getBottomAbs();
|
||||
Location top = plot.getTopAbs();
|
||||
|
||||
int minPlotX = Math.max(Math.min(bottom.getX(), top.getX()), minX);
|
||||
int minPlotY = Math.max(Math.min(bottom.getY(), top.getY()), minY);
|
||||
int minPlotZ = Math.max(Math.min(bottom.getZ(), top.getZ()), minZ);
|
||||
int maxPlotX = Math.min(Math.max(bottom.getX(), top.getX()), maxX);
|
||||
int maxPlotY = Math.min(Math.max(bottom.getY(), top.getY()), maxY);
|
||||
int maxPlotZ = Math.min(Math.max(bottom.getZ(), top.getZ()), maxZ);
|
||||
|
||||
if (minPlotX <= minX && minPlotY <= minY && minPlotZ <= minZ &&
|
||||
maxPlotX >= maxX && maxPlotY >= maxY && maxPlotZ >= maxZ) {
|
||||
return SectionPermissionChecker.ALL_ALLOWED;
|
||||
}
|
||||
|
||||
allowed.add(new Box(minPlotX - minX, minPlotY - minY, minPlotZ - minZ,
|
||||
maxPlotX - minX, maxPlotY - minY, maxPlotZ - minZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combine
|
||||
main:
|
||||
while (allowed.size() >= 2) {
|
||||
for (int i = 0; i < allowed.size() - 1; i++) {
|
||||
Box first = allowed.get(i);
|
||||
for (int j = i + 1; j < allowed.size(); j++) {
|
||||
Box second = allowed.get(j);
|
||||
|
||||
Box combined = first.tryCombine(second);
|
||||
if (combined != null) {
|
||||
allowed.remove(j);
|
||||
allowed.remove(i);
|
||||
allowed.add(combined);
|
||||
continue main;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SectionPermissionChecker.fromAllowedBoxes(allowed);
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ import com.moulberry.axiom.buffer.BiomeBuffer;
|
||||
import com.moulberry.axiom.buffer.BlockBuffer;
|
||||
import com.moulberry.axiom.buffer.CompressedBlockEntity;
|
||||
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
|
||||
import com.moulberry.axiom.integration.SectionPermissionChecker;
|
||||
import com.moulberry.axiom.integration.plotsquared.PlotSquaredIntegration;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@ -35,6 +37,7 @@ import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.lighting.LightEngine;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@ -116,6 +119,11 @@ public class SetBlockBufferPacketListener {
|
||||
continue;
|
||||
}
|
||||
|
||||
SectionPermissionChecker checker = PlotSquaredIntegration.checkSection(player.getBukkitEntity(), world.getWorld(), cx, cy, cz);
|
||||
if (checker != null && checker.noneAllowed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LevelChunk chunk = world.getChunk(cx, cz);
|
||||
|
||||
LevelChunkSection section = chunk.getSection(world.getSectionIndexFromSectionY(cy));
|
||||
@ -144,9 +152,28 @@ public class SetBlockBufferPacketListener {
|
||||
|
||||
Short2ObjectMap<CompressedBlockEntity> blockEntityChunkMap = buffer.getBlockEntityChunkMap(entry.getLongKey());
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int minX = 0;
|
||||
int minY = 0;
|
||||
int minZ = 0;
|
||||
int maxX = 15;
|
||||
int maxY = 15;
|
||||
int maxZ = 15;
|
||||
|
||||
if (checker != null) {
|
||||
minX = checker.bounds().minX();
|
||||
minY = checker.bounds().minY();
|
||||
minZ = checker.bounds().minZ();
|
||||
maxX = checker.bounds().maxX();
|
||||
maxY = checker.bounds().maxY();
|
||||
maxZ = checker.bounds().maxZ();
|
||||
if (checker.allAllowed()) {
|
||||
checker = null;
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
BlockState blockState = container.get(x, y, z);
|
||||
if (blockState == emptyState) continue;
|
||||
|
||||
@ -158,6 +185,8 @@ public class SetBlockBufferPacketListener {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checker != null && !checker.allowed(x, y, z)) continue;
|
||||
|
||||
BlockState old = section.setBlockState(x, y, z, blockState, true);
|
||||
if (blockState != old) {
|
||||
sectionChanged = true;
|
||||
@ -284,6 +313,9 @@ public class SetBlockBufferPacketListener {
|
||||
|
||||
var holder = registry.getHolder(biome);
|
||||
if (holder.isPresent()) {
|
||||
if (!PlotSquaredIntegration.canPlaceBlock(player.getBukkitEntity(),
|
||||
new Location(player.getBukkitEntity().getWorld(), x+1, y+1, z+1))) return;
|
||||
|
||||
container.set(x & 3, y & 3, z & 3, holder.get());
|
||||
changedChunks.add(chunk);
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren