24package com.dreamfirestudios.dreamcore.DreamLocationLimiter;
26import com.dreamfirestudios.dreamcore.DreamCore;
27import com.dreamfirestudios.dreamcore.DreamJava.DreamClassID;
29import org.bukkit.Location;
30import org.bukkit.World;
31import org.bukkit.entity.Player;
32import org.bukkit.util.Vector;
34import java.lang.reflect.Method;
35import java.util.ArrayList;
37import java.util.Objects;
63 private final List<Player> players =
new ArrayList<>();
67 @Getter
private String edgeMessage =
"You have reached the edge of the location!";
68 @Getter
private Location originPoint;
69 @Getter
private int distanceExtents = 10;
70 @Getter
private boolean stopped =
false;
72 private World originWorld;
88 if (player ==
null)
return;
89 if (players.contains(player))
return;
94 if (!canPlayerBeLimited(player))
return;
107 if (player ==
null)
return;
108 if (!players.remove(player))
return;
117 if (originPoint ==
null || originPoint.getWorld() ==
null) {
118 throw new IllegalStateException(
"Origin point/world must be set before starting the limiter.");
120 originWorld = originPoint.getWorld();
123 for (Player player : players) {
124 safeTeleport(player, originPoint);
138 if (originPoint ==
null || originWorld ==
null)
return;
140 for (Player player :
new ArrayList<>(players)) {
141 if (player ==
null || !player.isOnline())
continue;
143 if (!Objects.equals(player.getWorld(), originWorld)) {
144 safeTeleport(player, originPoint);
148 final double distance = player.getLocation().distance(originPoint);
149 if (distance >= distanceExtents) {
150 handleOutOfBoundsPlayer(player, distance);
163 private void handleOutOfBoundsPlayer(Player player,
double distance) {
164 if (edgeMessage !=
null && !edgeMessage.isEmpty()) {
165 player.sendMessage(edgeMessage);
168 switch (locationLimiterType) {
170 safeTeleport(player, originPoint);
171 new LocationLimiterLimitHit(
this, player);
174 pushPlayerBack(player);
175 new LocationLimiterLimitHit(
this, player);
184 private void pushPlayerBack(Player player) {
185 Vector toOrigin = originPoint.toVector().subtract(player.getLocation().toVector()).normalize();
186 player.setVelocity(toOrigin.multiply(0.5));
194 this.stopped = !state;
210 this.edgeMessage = message ==
null ?
"" : message;
218 if (extents <= 0)
throw new IllegalArgumentException(
"Distance extents must be > 0");
219 this.distanceExtents = extents;
227 this.locationLimiterType = Objects.requireNonNull(type,
"type");
235 if (origin ==
null || origin.getWorld() ==
null)
236 throw new IllegalArgumentException(
"Origin point/world cannot be null.");
237 this.originPoint = origin;
238 this.originWorld = origin.getWorld();
241 @SuppressWarnings(
"unchecked")
242 private
boolean canPlayerBeLimited(Player player) {
244 Class<?> actionEnum = Class.forName(
"com.dreamfirestudios.dreamcore.DreamfirePlayerAction");
245 Class<?> apiClass = Class.forName(
"com.dreamfirestudios.dreamcore.DreamfirePlayerActionAPI");
247 Object actionValue = Enum.valueOf((Class<Enum>) actionEnum,
"PlayerLocationLimiter");
248 Method m = apiClass.getMethod(
"CanPlayerAction", actionEnum, UUID.class);
249 Object result = m.invoke(
null, actionValue, player.getUniqueId());
250 return result instanceof Boolean && (Boolean) result;
251 }
catch (Throwable ignored) {
256 private void safeTeleport(Player player, Location target) {
257 if (player ==
null || target ==
null || target.getWorld() ==
null)
return;
258 player.teleport(target);
281 private final List<Player> players =
new ArrayList<>();
284 private String edgeMessage =
"You have reached the edge of the location!";
285 private int extents = 10;
288 if (player !=
null) this.players.add(player);
293 this.type = Objects.requireNonNull(type,
"type");
298 this.start = Objects.requireNonNull(start,
"start");
303 if (message !=
null && !message.isBlank()) this.edgeMessage = message;
308 if (distance <= 0)
throw new IllegalArgumentException(
"Distance extents must be > 0");
309 this.extents = distance;
319 if (originPoint ==
null || originPoint.getWorld() ==
null)
320 throw new IllegalArgumentException(
"Origin point/world cannot be null.");
322 limiter.locationLimiterType = this.type;
323 limiter.locationLimiterStart = this.start;
324 limiter.edgeMessage = this.edgeMessage;
325 limiter.distanceExtents = this.extents;
326 limiter.originPoint = originPoint;
327 limiter.originWorld = originPoint.getWorld();
328 for (Player p : players) limiter.
AddPlayer(p);
static final LinkedHashMap< UUID, DreamLocationLimiter > DreamLocationLimiters
Fluent builder for DreamLocationLimiter.
LocationLimiterBuilder edgeMessage(String message)
LocationLimiterBuilder extents(int distance)
DreamLocationLimiter build(Location originPoint)
Builds a new limiter and registers it with DreamCore.
LocationLimiterBuilder start(LocationLimiterStart start)
LocationLimiterBuilder type(LocationLimiterType type)
LocationLimiterBuilder addPlayer(Player player)
Runtime limiter that constrains players to a defined radius around an origin point.
void setLocationLimiterType(LocationLimiterType type)
Updates the limiter type.
void RemovePlayer(Player player)
Removes a player from this limiter.
void toggleLocationLimiter(boolean state)
Enables or disables limiter enforcement.
void setOriginPoint(Location origin)
Updates the origin point.
void startLocationLimiter()
Starts the limiter and teleports players to origin if configured.
void stopLocationLimiter()
Stops this limiter and unregisters it from DreamCore.
void AddPlayer(Player player)
Adds a player to this limiter.
void setEdgeMessage(String message)
Updates the edge message.
void tickLocationLimiter()
Main tick handler that enforces the limiter each loop.
void setDistanceExtents(int extents)
Updates the distance extent (radius).
Event fired when a player is about to be added to a DreamLocationLimiter.
boolean isCancelled()
Whether the event is cancelled.
Event fired after a player is removed from a DreamLocationLimiter.
Starting modes for DreamLocationLimiter.
ORIGIN_POINT
Teleports all players to the origin point when the limiter starts.
Behavior of DreamLocationLimiter when players exceed the boundary.
SNAP_TO_ORIGIN
Instantly teleport the player back to origin.