Last active
March 17, 2019 23:34
-
-
Save Joo200/0289b48931a11c5e6d7884985b6f3fd9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 + ")"; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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