This commit is contained in:
kento2 2026-06-28 19:01:06 +02:00
parent 6087b98705
commit 63a4f17a76
21 changed files with 484 additions and 27 deletions

View file

@ -3,6 +3,7 @@ package de.kentoj.scrow.bukkit;
import de.kentoj.kencommandapi.BukkitKenCommandApi;
import de.kentoj.scrow.bukkit.friends.FriendRequestService;
import de.kentoj.scrow.bukkit.friends.FriendshipService;
import de.kentoj.scrow.bukkit.region.RegionManager;
import de.kentoj.scrowlib.connection.DatabaseConnectionFactory;
import de.kentoj.scrowlib.servermanager.ServerManager;
import io.nats.client.Connection;
@ -19,8 +20,6 @@ public class ScrowAPI {
@Getter
private static DatabaseConnectionFactory dbConFactory;
@Getter
private static BukkitKenCommandApi commandApi;
@Getter
private static Scheduler minecraftScheduler;
@Getter
private static EconomyService economyService;
@ -32,17 +31,16 @@ public class ScrowAPI {
private static Connection nats;
@Getter
private static ServerManager serverManager;
@Getter
private static final RegionManager regionManager = new RegionManager();
@Getter
private static final BukkitKenCommandApi commandApi = new BukkitKenCommandApi();
@ApiStatus.Internal
public static void setEconomyService(EconomyService economyService) {
ScrowAPI.economyService = economyService;
}
@ApiStatus.Internal
public static void setCommandApi(BukkitKenCommandApi commandApi) {
ScrowAPI.commandApi = commandApi;
}
@ApiStatus.Internal
public static void setMinecraftScheduler(Scheduler minecraftScheduler) {
ScrowAPI.minecraftScheduler = minecraftScheduler;

View file

@ -0,0 +1,14 @@
package de.kentoj.scrow.bukkit.region;
import lombok.Value;
import org.bukkit.Chunk;
@Value
public class ChunkPos {
int x;
int z;
public static ChunkPos fromChunk(Chunk chunk) {
return new ChunkPos(chunk.getX(), chunk.getZ());
}
}

View file

@ -0,0 +1,27 @@
package de.kentoj.scrow.bukkit.region;
import lombok.Getter;
@Getter
public final class Range {
private final double min;
private final double max;
public boolean contains(double num) {
return min <= num && num <= max;
}
public double getLength() {
return max - min;
}
public Range(double a, double b) {
if (a < b) {
min = a;
max = b;
} else {
min = b;
max = a;
}
}
}

View file

@ -0,0 +1,42 @@
package de.kentoj.scrow.bukkit.region;
import de.kentoj.scrow.bukkit.region.impl.Region;
import java.util.*;
public class RegionManager {
private final Map<Long, List<UUID>> chunkIndex = new HashMap<>();
private final Map<UUID, Region> regions = new HashMap<>();
public List<Region> getRegions(ChunkPos chunkPos) {
long key = toKey(chunkPos.getX(), chunkPos.getZ());
var uuids = chunkIndex.get(key);
if (uuids == null) return Collections.emptyList();
return uuids.stream().map(regions::get).toList();
}
public void registerRegion(Region region) {
for (ChunkPos chunkPos : region.getChunks()) {
var key = toKey(chunkPos.getX(), chunkPos.getZ());
chunkIndex.computeIfAbsent(key, __ -> new ArrayList<>())
.add(region.getUuid());
}
regions.put(region.getUuid(), region);
}
public void unregisterRegion(Region region) {
for (ChunkPos chunkPos : region.getChunks()) {
var key = toKey(chunkPos.getX(), chunkPos.getZ());
var list = chunkIndex.get(key);
if (list == null) return;
list.remove(region.getUuid());
}
regions.remove(region.getUuid());
}
public long toKey(int x, int z) {
// chatgpt
return (((long) x) << 32) ^ (z & 0xffffffffL);
}
}

View file

@ -0,0 +1,14 @@
package de.kentoj.scrow.bukkit.region.event;
import de.kentoj.scrow.bukkit.region.impl.Region;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
@RequiredArgsConstructor
@Getter
public abstract class RegionEvent extends Event {
private final Region region;
private final Player player;
}

View file

@ -0,0 +1,32 @@
package de.kentoj.scrow.bukkit.region.event;
import de.kentoj.scrow.bukkit.region.impl.Region;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class RegionJoinEvent extends RegionEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Setter
@Getter
private boolean isCancelled;
public RegionJoinEvent(Region region, Player player) {
super(region, player);
}
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View file

@ -0,0 +1,31 @@
package de.kentoj.scrow.bukkit.region.event;
import de.kentoj.scrow.bukkit.region.impl.Region;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class RegionLeaveEvent extends RegionEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@Setter
@Getter
private boolean isCancelled;
public RegionLeaveEvent(Region region, Player player) {
super(region, player);
}
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View file

@ -0,0 +1,11 @@
package de.kentoj.scrow.bukkit.region.impl;
import lombok.Getter;
import java.util.UUID;
public abstract class AbstractRegion implements Region {
@Getter
private final UUID uuid = UUID.randomUUID();
}

View file

@ -0,0 +1,45 @@
package de.kentoj.scrow.bukkit.region.impl;
import de.kentoj.scrow.bukkit.region.ChunkPos;
import de.kentoj.scrow.bukkit.region.Range;
import org.bukkit.Location;
import java.util.ArrayList;
import java.util.List;
public class CuboidRegion extends AbstractRegion {
private final Range xRange;
private final Range yRange;
private final Range zRange;
public CuboidRegion(Location loc1, Location loc2) {
xRange = new Range(loc1.getX(), loc2.getX());
yRange = new Range(loc1.getY(), loc2.getY());
zRange = new Range(loc1.getY(), loc2.getY());
}
@Override
public boolean isInRegion(Location location) {
return xRange.contains(location.getX())
&& yRange.contains(location.getY())
&& zRange.contains(location.getZ());
}
@Override
public List<ChunkPos> getChunks() {
List<ChunkPos> res = new ArrayList<>();
int minChunkX = (int) Math.floor(xRange.getMin()) << 4;
int maxChunkX = (int) Math.ceil(xRange.getMax()) << 4;
for (int chunkX = minChunkX; chunkX < maxChunkX; chunkX++) {
int minChunkZ = (int) Math.floor(zRange.getMin()) << 4;
int maxChunkZ = (int) Math.ceil(zRange.getMax()) << 4;
for (int chunkZ = minChunkZ; chunkZ < maxChunkZ; chunkZ++) {
res.add(new ChunkPos(chunkX, chunkZ));
}
}
return res;
}
}

View file

@ -0,0 +1,42 @@
package de.kentoj.scrow.bukkit.region.impl;
import de.kentoj.scrow.bukkit.region.ChunkPos;
import lombok.RequiredArgsConstructor;
import org.bukkit.Location;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor
public class CylinderRegion extends AbstractRegion {
private final Location center;
private final double height;
private final double radius;
@Override
public boolean isInRegion(Location location) {
if (location.getY() < center.getY()) return false;
if (location.getY() > center.getY() + height) return false;
double diffX = location.getX() - center.getX();
double diffZ = location.getZ() - center.getZ();
return diffX * diffX + diffZ * diffZ <= radius * radius;
}
@Override
public List<ChunkPos> getChunks() {
List<ChunkPos> res = new ArrayList<>();
int a = (int) Math.ceil(radius / 16);
var centerChunkX = center.getBlockX() >> 4;
var centerChunkZ = center.getBlockZ() >> 4;
for (int x = -a; x <= a; x++) {
for (int z = -a; z <= a; z++) {
res.add(new ChunkPos(centerChunkX + x, centerChunkZ + z));
}
}
return res;
}
}

View file

@ -0,0 +1,39 @@
package de.kentoj.scrow.bukkit.region.impl;
import de.kentoj.scrow.bukkit.region.ChunkPos;
import lombok.RequiredArgsConstructor;
import org.bukkit.Location;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* region consisting of multiple regions
*/
@RequiredArgsConstructor
public class MergedRegion extends AbstractRegion {
private final Region[] regions;
@Override
public boolean isInRegion(Location location) {
for (Region region : regions) {
if (region.isInRegion(location)) return true;
}
return false;
}
@Override
public List<ChunkPos> getChunks() {
return Arrays.stream(regions)
.map(Region::getChunks)
.reduce(new ArrayList<>(), (list, chunks) -> {
list.addAll(chunks);
return list;
})
.stream()
.distinct()
.toList();
}
}

View file

@ -0,0 +1,19 @@
package de.kentoj.scrow.bukkit.region.impl;
import de.kentoj.scrow.bukkit.region.ChunkPos;
import org.bukkit.Location;
import java.util.List;
import java.util.UUID;
public interface Region {
/**
* A random uuid assigned to the Region at creation
*/
UUID getUuid();
boolean isInRegion(Location location);
List<ChunkPos> getChunks();
}