Skip to content

Instantly share code, notes, and snippets.

@Joo200
Last active March 17, 2019 23:34
Show Gist options
  • Select an option

  • Save Joo200/0289b48931a11c5e6d7884985b6f3fd9 to your computer and use it in GitHub Desktop.

Select an option

Save Joo200/0289b48931a11c5e6d7884985b6f3fd9 to your computer and use it in GitHub Desktop.
package dump.package;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class RandomPointGetter {
private TeleportTarget target;
private SafePointInterface safePoint;
private RandomPoint randomPoint;
private static final int TRIES = 25;
public RandomPointGetter(TeleportTarget target) {
this.target = target;
safePoint = SafePointInterface.getInterface(target.getWorld());
randomPoint = new RandomPoint();
}
public CompletableFuture<Location> single() {
return single(0, true);
}
private CompletableFuture<Location> single(int counter, boolean throwException) {
Location loc = randomPoint.getNext();
return target.getWorld().getChunkAtAsync(loc, false)
.thenApply(chunk -> safePoint.getSafeLocation(loc, target.getMinHeight(), target.getMaxHeight()))
.thenCompose(location -> {
if(location == null) {
if(counter >= TRIES && throwException)
throw new RuntimeException(ChatColor.RED + "No point.");
else if(counter >= TRIES) {
return CompletableFuture.completedFuture(null);
}
return single(counter + 1, throwException);
}
location.setDirection(location.toVector().multiply(-1).setY(0).normalize());
return CompletableFuture.completedFuture(location);
});
}
public <T> CompletableFuture<Void> fillMap(Map<T, Location> map, int radius) {
return fillMap(map, radius == 0 ? 20 : radius, 0);
}
private <T> CompletableFuture<Void> fillMap(Map<T, Location> map, int radius, int counter) {
Bukkit.getLogger().info("Getting locations for map. Counter = " + counter);
return single(0, false).thenCompose(location -> {
if(location == null) {
throw new RuntimeException(ChatColor.RED + "No point.");
} else return CompletableFuture.completedFuture(location);
}).thenApply(
location -> {
Location copy = location.clone();
copy.setDirection(copy.toVector().multiply(-1).setY(0).normalize());
map.putIfAbsent(getFirst(map), copy);
Bukkit.getLogger().info("Middle = " + location.toString());
return location;
}
).thenAccept(location -> fillMap(map, location, radius))
.thenCompose(nothing -> {
if(map.values().contains(null)) {
Bukkit.getLogger().info("Map contains null.");
if(counter >= TRIES)
throw new RuntimeException(ChatColor.RED + "No point.");
return fillMap(map, radius, counter + 1);
}
return CompletableFuture.completedFuture(null);
});
}
public static Throwable getThrowable(Throwable t) {
while(t instanceof CompletionException)
t = t.getCause();
return t;
}
private <T> void fillMap(Map<T, Location> map, Location offset, int radius) {
for (Map.Entry<T, Location> tLocationEntry : map.entrySet()) {
if(tLocationEntry.getValue() != null) continue;
for(int counter = 0; counter < TRIES; counter++) {
Location withOffest = randomPoint.getWithOffest(offset, radius);
//TODO: load those chunks async
Location safeLocation = safePoint.getSafeLocation(withOffest, target.getMinHeight(), target.getMaxHeight());
if(safeLocation != null) {
Location copy = safeLocation.clone();
copy.setDirection(copy.toVector().multiply(-1).setY(0).normalize());
tLocationEntry.setValue(copy);
break;
}
}
if(tLocationEntry.getValue() != null)
Bukkit.getLogger().info("Location found: " + tLocationEntry.getValue().toString());
else
Bukkit.getLogger().info("Null point found.");
}
if(map.values().contains(null))
throw new RuntimeException(ChatColor.RED + "No point found.");
}
private static <T,V> T getFirst(Map<T,V> map) {
if(map.keySet().isEmpty()) return null;
return map.keySet().iterator().next();
}
public final class RandomPoint {
public Location getNext() {
int radius = (int) (Math.random() * (target.getRadiusMax() - target.getRadiusMin())) + target.getRadiusMin();
float angle = (float) (Math.random() * 360);
int x = (int) (Math.sin(angle) * radius); // North: x= 0; East: x=1
int z = -(int) (Math.cos(angle) * radius); // North: z=-1; East: z=0
return new Location(target.getWorld(), x, (int)((target.getMaxHeight()+target.getMinHeight())/2), z);
}
public Location getWithOffest(Location offset, int r) {
int radius = (int) (Math.random() * r);
float angle = (float) (Math.random() * 360);
int x = (int) (offset.getBlockX() + Math.sin(angle) * radius); // North: x= 0; East: x=1
int z = -(int) (offset.getBlockZ() + Math.cos(angle) * radius); // North: z=-1; East: z=0
return new Location(target.getWorld(), x, (int)((target.getMaxHeight()+target.getMinHeight())/2), z);
}
}
}
package dump.package;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
public interface SafePointInterface {
Location getSafeLocation(Location location);
Location getSafeLocation(Location location, int minY, int maxY);
static SafePointInterface getInterface(World world) {
if(world.getEnvironment() == World.Environment.NETHER)
return new SafePointNether();
return new SafePointOverworld();
}
class SafePointOverworld implements SafePointInterface {
@Override
public Location getSafeLocation(Location location) {
Block highestBlockAt = location.getWorld().getHighestBlockAt(location).getRelative(BlockFace.DOWN, 1);
if(highestBlockAt == null) return null;
if(highestBlockAt.getType() == Material.WATER || highestBlockAt.getType() == Material.LAVA) {
return null;
}
if(highestBlockAt.isLiquid()) return null;
if(!highestBlockAt.getType().isSolid()) return null;
return highestBlockAt.getLocation().add(0.5, 1, 0.5);
}
@Override
public Location getSafeLocation(Location location, int minY, int maxY) {
Location loc = getSafeLocation(location);
if(loc == null) return null;
if(minY > loc.getBlockY() || maxY < loc.getBlockY())
return null;
return loc;
}
}
class SafePointNether implements SafePointInterface {
@Override
public Location getSafeLocation(Location location) {
int start = (int)(Math.random() * 124);
Location counterLoc = location.clone();
for(int counter = start + 1; counter != start; counter = (counter+1)%127) {
if(counter == 0) continue;
counterLoc.setY(counter);
if(checkLocation(counterLoc)) {
Location returnVal = location.clone();
returnVal.setY(counter);
returnVal.add(0.5, 0, 0.5);
return returnVal;
}
}
return null;
}
@Override
public Location getSafeLocation(Location location, int minY, int maxY) {
if(minY < 1) minY = 1;
Location counterLoc = location.clone();
for(int counter = 0; counter < maxY-minY; counter++) {
counterLoc.add(0, 1, 0);
if(checkLocation(counterLoc))
return counterLoc.add(0.5, 0, 0.5);
}
return null;
}
private static boolean checkLocation(Location location) {
Block under = location.subtract(0, 1, 0).getBlock();
Block current = location.getBlock();
Block upper = location.add(0, 1, 0).getBlock();
return under.getType().isSolid() && under.getType() != Material.MAGMA_BLOCK &&
current.getType() == Material.AIR && upper.getType() == Material.AIR;
}
}
}
package dump.package;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TeleportTarget {
private String world;
private int radiusMin, radiusMax;
private int minHeight, maxHeight;
private int groupRadius;
private int sec;
public TeleportTarget(String world, int radiusMin, int radiusMax, int minHeight, int maxHeight, int groupRadius, int sec) {
this.world = world;
this.radiusMax = radiusMax;
this.radiusMin = radiusMin;
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.sec = sec;
}
public TeleportTarget(Map<String, String> map) throws InvalidFlagFormat {
if(!map.keySet().containsAll(Set.of("World", "minR", "maxR", "minH", "maxH", "secs", "groupR")))
throw new InvalidFlagFormat("Missing Flag.");
this.world = map.get("World");
if(Bukkit.getWorld(world) == null)
throw new InvalidFlagFormat("Unknown World: " + world);
try {
radiusMax = Integer.parseInt(map.get("maxR"));
radiusMin = Integer.parseInt(map.get("minR"));
minHeight = Integer.parseInt(map.get("minH"));
maxHeight = Integer.parseInt(map.get("maxH"));
sec = Integer.parseInt(map.get("secs"));
groupRadius = Integer.parseInt(map.get("groupR"));
} catch (NumberFormatException e) {
throw new InvalidFlagFormat("Not a number.");
}
}
public Map<String, String> toMap() {
Map<String, String> keyValueMap = new HashMap<>();
keyValueMap.put("World", getWorld().getName());
keyValueMap.put("minR", String.valueOf(getRadiusMin()));
keyValueMap.put("maxR", String.valueOf(getRadiusMax()));
keyValueMap.put("minH", String.valueOf(getMinHeight()));
keyValueMap.put("maxH", String.valueOf(getRadiusMin()));
keyValueMap.put("secs", String.valueOf(getRadiusMin()));
keyValueMap.put("groupR", String.valueOf(getGroupRadius()));
return keyValueMap;
}
public World getWorld() {
return Bukkit.getWorld(world);
}
public int getRadiusMax() {
return radiusMax;
}
public int getRadiusMin() {
return radiusMin;
}
public int getMinHeight() {
return minHeight;
}
public int getMaxHeight() {
return maxHeight;
}
public int getGroupRadius() {
return groupRadius;
}
public int getSafeSecs() {
return sec;
}
@Override
public String toString() {
return "(World: " + world + ", RadiusMin: " + radiusMin + ", RadiusMax: " + radiusMax +
", MinHeight: " + minHeight + ", MaxHeight" + maxHeight + ", GroupRadius: " + groupRadius +
", SafeTime: " + sec + ")";
}
}
package dump.package;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import javax.annotation.Nullable;
import java.util.*;
public class TeleportTargetFlag extends Flag<TeleportTarget> {
public TeleportTargetFlag(String name) {
super(name);
}
private static String format = "Format: World=<world>,minR=<minR>,maxR=<maxR>,minH=<minH>,maxH=<maxH>,secs=<secs>,groupR=<groupR>";
@Override
public TeleportTarget parseInput(FlagContext flagContext) throws InvalidFlagFormat {
String[] args = flagContext.getUserInput().split(",");
ProtectedRegion region = (ProtectedRegion)flagContext.get("region");
assert region != null;
TeleportTarget currentFlag = region.getFlag(FarmworldPlugin.TELEPORT_FLAG);
Map<String, String> keyValueMap = new HashMap<>();
if(currentFlag != null) {
keyValueMap = currentFlag.toMap();
}
for (String arg : args) {
String[] split = arg.split("=");
if(split.length != 2)
throw new InvalidFlagFormat("Invalid Format: " + format);
keyValueMap.put(split[0], split[1]);
}
return new TeleportTarget(keyValueMap);
}
@Override
public TeleportTarget unmarshal(@Nullable Object o) {
if(!(o instanceof Map)) {
return null;
}
Map<String, String> map = (Map<String, String>)o;
try {
return new TeleportTarget(map);
} catch (InvalidFlagFormat invalidFlagFormat) {
return null;
}
}
@Override
public Object marshal(TeleportTarget o) {
return o.toMap();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment