67 private static final Random RANDOM =
new Random(System.currentTimeMillis());
70 private static final char[] VALID_CHARS = {
'_',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'/'};
74 return 100D * progress / total;
79 return NumberFormat.getInstance().format(amount);
84 return NumberFormat.getInstance().format(amount);
89 return NumberFormat.getInstance().format(amount);
94 if (amount >= 0 && amount < 1_000)
96 if (amount >= 1_000 && amount < 1_000_000) {
97 return (amount / 1_000) +
"K";
99 if (amount >= 1_000_000 && amount < 1_000_000_000) {
100 return (amount / 1_000_000) +
"M";
102 if (amount >= 1_000_000_000 && amount < Integer.MAX_VALUE) {
103 return (amount / 1_000_000_000) +
"B";
105 return "<col=fc2a2a>Lots!";
108 public static long stringToLong(String
string) {
110 for (
int i = 0; i <
string.length() && i < 12; i++) {
111 char c =
string.charAt(i);
113 if (c >=
'A' && c <=
'Z')
115 else if (c >=
'a' && c <=
'z')
117 else if (c >=
'0' && c <=
'9')
120 while (l % 37L == 0L && l != 0L)
131 public static String
rank(
final String
string) {
132 return Stream.of(
string.trim().split(
"\\s")).filter(word -> word.length() > 0).map(word -> word.substring(0, 1).toUpperCase() + word.substring(1)).collect(Collectors.joining(
" "));
138 boolean capitalize =
true;
139 StringBuilder sb =
new StringBuilder(
string);
140 while (pos < sb.length()) {
141 if (sb.charAt(pos) ==
'.') {
143 }
else if (capitalize && !Character.isWhitespace(sb.charAt(pos))) {
144 sb.setCharAt(pos, Character.toUpperCase(sb.charAt(pos)));
149 return sb.toString();
155 char c = nextWord.toUpperCase().charAt(0);
156 if (c ==
'A' || c ==
'E' || c ==
'I' || c ==
'O' || c ==
'U') {
164 return new SimpleDateFormat(
"EE MMM dd yyyy").format(
new Date());
169 return new SimpleDateFormat(
"yyyy/MM/dd").format(
new Date());
174 return Words.getInstance(amount).getNumberInWords();
179 return new SimpleDateFormat(
"hh:mm aa").format(
new Date());
184 return new SimpleDateFormat(
"m:ss").format(period);
187 public static String bigDaddyTime(
long period) {
188 return new SimpleDateFormat(
"HH:mm:ss").format(period);
198 long secs = ticks * 3 / 5;
201 return "0:" + (secs < 10 ?
"0" :
"") + secs;
204 long mins = secs / 60;
205 long remainderSecs = secs - (mins * 60);
207 return mins +
":" + (remainderSecs < 10 ?
"0" :
"") + remainderSecs +
"";
210 long hours = mins / 60;
211 long remainderMins = mins - (hours * 60);
213 return hours +
"h " + (remainderMins < 10 ?
"0" :
"") + remainderMins +
"m " + (remainderSecs < 10 ?
"0" :
"") + remainderSecs +
"s";
216 long days = hours / 24;
217 long remainderHrs = hours - (days * 24);
218 return days +
"d " + (remainderHrs < 10 ?
"0" :
"") + remainderHrs +
"h " + (remainderMins < 10 ?
"0" :
"") + remainderMins +
"m";
224 for (
int index = 0; index < text.length() && index < 12; index++) {
225 char key = text.charAt(index);
227 if (key >=
'A' && key <=
'Z')
228 hash += (1 + key) - 65;
229 else if (key >=
'a' && key <=
'z')
230 hash += (1 + key) - 97;
231 else if (key >=
'0' && key <=
'9')
232 hash += (27 + key) - 48;
234 while (hash % 37L == 0L && hash != 0L)
239 public static String longToString(
long l) {
240 if (l <= 0L || l >= 0x5b5b57f8a98a5dd1L)
245 char ac[] =
new char[12];
249 ac[11 - i++] = VALID_CHARS[(int) (l1 - l * 37L)];
251 return new String(ac, 12 - i, i);
254 public static long hash(String input) {
259 for (
int index = 0; index < input.length() && index < 12; index++) {
260 char key = input.charAt(index);
262 if (key >=
'A' && key <=
'Z') {
263 hash += (1 + key) - 65;
264 }
else if (key >=
'a' && key <=
'z') {
265 hash += (1 + key) - 97;
266 }
else if (key >=
'0' && key <=
'9') {
267 hash += (27 + key) - 48;
270 while (hash % 37L == 0L && hash != 0L) {
276 public static int random(
int bound) {
277 return random(0, bound,
false);
280 public static int random(
int lowerBound,
int upperBound) {
281 return random(lowerBound, upperBound,
false);
286 return new ArrayList<T>(collection).get((
int) (RANDOM.nextDouble() * collection.size()));
291 return list.get((
int) (RANDOM.nextDouble() * list.size()));
294 public static boolean hasOneOutOf(
double chance) {
299 return random(1, (
int) chance) <= 100;
304 return array[(int) (RANDOM.nextDouble() * array.length)];
309 return array[(int) (RANDOM.nextDouble() * array.length)];
312 public static int random(
int lowerBound,
int upperBound,
boolean inclusive) {
313 if (lowerBound >= upperBound) {
314 throw new IllegalArgumentException(
"The lower bound cannot be larger than or equal to the upper bound!");
317 return lowerBound + RANDOM.nextInt(upperBound - lowerBound) + (inclusive ? 1 : 0);
322 List<Object> classes =
new LinkedList<>();
323 File dir =
new File(directory);
324 if (!dir.exists() || !dir.isDirectory()) {
328 File[] files = dir.listFiles();
332 for (File f : files) {
333 if (f.isDirectory() || f.getName().contains(
"$")) {
336 String domainPath =
Utility.class.getProtectionDomain().getCodeSource().getLocation().getPath().replace(
"/",
"\\");
337 String filePath =
"\\" + f.getPath();
338 String clazzName = filePath.replace(domainPath,
"");
339 clazzName = clazzName.replace(
"\\",
".");
340 clazzName = clazzName.replace(
".class",
"");
341 Class<?> clazz = Class.forName(clazzName);
342 Object o = clazz.getDeclaredConstructor().newInstance();
345 }
catch (ClassNotFoundException | IllegalAccessException | InstantiationException
346 | InvocationTargetException | NoSuchMethodException e) {
354 String filePath = clazz.getResource(
"/" + clazz.getName().replace(
".",
"/") +
".class").getFile();
355 File file =
new File(filePath);
356 File directory = file.getParentFile();
357 List<String> list =
new ArrayList<>();
359 File[] files = directory.listFiles();
362 return Collections.emptyList();
365 for (File f : files) {
366 if (f.isDirectory()) {
367 list.add(f.getPath());
371 String[] directories = list.toArray(
new String[0]);
372 return Arrays.asList(directories);
383 boolean changed =
false;
387 }
else if (diffX >= 88) {
393 }
else if (diffY >= 88) {
400 public static int getDistance(Interactable source, Position target) {
401 Position sourceTopRight = source.getPosition().transform(source.width() - 1, source.length() - 1);
405 if (sourceTopRight.getX() < target.getX()) {
406 dx = target.getX() - sourceTopRight.getX();
407 }
else if (source.getX() > target.getX()) {
408 dx = source.getX() - target.getX();
413 if (sourceTopRight.getY() < target.getY()) {
414 dy = target.getY() - sourceTopRight.getY();
415 }
else if (source.getY() > target.getY()) {
416 dy = source.getY() - target.getY();
424 public static int getDistance(Position source,
int sourceWidth,
int sourceLength, Position target,
int targetWidth,
int targetLength) {
425 if (source.getHeight() != target.getHeight()) {
426 return Integer.MAX_VALUE;
429 if (sourceWidth <= 0) sourceWidth = 1;
430 if (sourceLength <= 0) sourceLength = 1;
431 if (targetWidth <= 0) targetWidth = 1;
432 if (targetLength <= 0) targetLength = 1;
434 Position sourceTopRight = source.transform(sourceWidth - 1, sourceLength - 1, 0);
435 Position targetTopRight = target.transform(targetWidth - 1, targetLength - 1, 0);
439 if (sourceTopRight.getX() < target.getX()) {
440 dx = target.getX() - sourceTopRight.getX();
441 }
else if (source.getX() > targetTopRight.getX()) {
442 dx = source.getX() - targetTopRight.getX();
447 if (sourceTopRight.getY() < target.getY()) {
448 dy = target.getY() - sourceTopRight.getY();
449 }
else if (source.getY() > targetTopRight.getY()) {
450 dy = source.getY() - targetTopRight.getY();
458 public static Position getDelta(Position source,
int sourceWidth,
int sourceLength, Position target,
int targetWidth,
int targetLength) {
459 if (source.getHeight() != target.getHeight()) {
460 return Position.create(Integer.MAX_VALUE, Integer.MAX_VALUE);
463 if (sourceWidth <= 0) sourceWidth = 1;
464 if (sourceLength <= 0) sourceLength = 1;
465 if (targetWidth <= 0) targetWidth = 1;
466 if (targetLength <= 0) targetLength = 1;
468 Position sourceTopRight = source.transform(sourceWidth - 1, sourceLength - 1, 0);
469 Position targetTopRight = target.transform(targetWidth - 1, targetLength - 1, 0);
473 if (sourceTopRight.getX() < target.getX()) {
474 dx = target.getX() - sourceTopRight.getX();
475 }
else if (source.getX() > targetTopRight.getX()) {
476 dx = source.getX() - targetTopRight.getX();
481 if (sourceTopRight.getY() < target.getY()) {
482 dy = target.getY() - sourceTopRight.getY();
483 }
else if (source.getY() > targetTopRight.getY()) {
484 dy = source.getY() - targetTopRight.getY();
489 return Position.create(dx, dy);
492 public static int getDistance(Interactable source, Interactable target) {
493 return getDistance(source.getPosition(), source.width(), source.length(), target.getPosition(), target.width(), target.length());
496 public static Position getDelta(Interactable source, Interactable target) {
497 return getDelta(source.getPosition(), source.width(), source.length(), target.getPosition(), target.width(), target.length());
500 public static Position getDelta(Position source, Position target) {
501 int dx = target.getX() - source.getX();
502 int dy = target.getY() - source.getY();
503 return Position.create(dx, dy);
507 public static boolean withinDistance(Interactable source, Interactable target,
int radius) {
508 return within(source, target, radius);
511 public static boolean withinDistance(Interactable source, Position target,
int radius) {
512 return within(source.getPosition(), source.width(), source.length(), target, 1, 1, radius);
515 public static Position findAccessableTile(Interactable source) {
516 Position found =
null;
517 Position[] positions = getBoundaries(source);
519 for (Position next : positions) {
520 Direction direction = Direction.getDirection(source.getPosition(), next);
522 if (inside(next, 0, 0, source.getPosition(), source.width(), source.length())) {
526 if (TraversalMap.isTraversable(next, direction,
false)) {
535 public static Position findBestInside(Interactable source, Interactable target) {
536 if (target.width() <= 1 || target.length() <= 1) {
537 return target.getPosition();
540 int dx, dy, dist = Integer.MAX_VALUE;
541 Position best = source.getPosition();
543 for (
int x = 0; x < target.width(); x++) {
544 Position boundary = target.getPosition().transform(x, 0);
545 int distance = getDistance(source, boundary);
547 if (dist > distance) {
552 boundary = target.getPosition().transform(x, target.length() - 1);
553 distance = getDistance(source, boundary);
555 if (dist > distance) {
561 for (
int y = 0; y < target.length(); y++) {
562 Position boundary = target.getPosition().transform(0, y);
563 int distance = getDistance(source, boundary);
565 if (dist > distance) {
570 boundary = target.getPosition().transform(target.width() - 1, y);
571 distance = getDistance(source, boundary);
573 if (dist > distance) {
579 if (best.equals(source.getPosition())) {
580 return source.getPosition();
583 Direction direction = Direction.getDirection(source.getPosition(), best);
584 Position sourceTopRight = source.getPosition().transform(source.width() - 1, source.length() - 1, 0);
586 if (source.getX() > best.getX()) {
587 dx = best.getX() - source.getX();
588 }
else if (sourceTopRight.getX() < best.getX()) {
589 dx = best.getX() - sourceTopRight.getX();
591 dx = direction.getDirectionX();
593 if (source.getY() > best.getY()) {
594 dy = best.getY() - source.getY();
595 }
else if (sourceTopRight.getY() < best.getY()) {
596 dy = best.getY() - sourceTopRight.getY();
598 dy = direction.getDirectionY();
601 return source.getPosition().transform(dx, dy);
604 public static void fixInsidePosition(Mob source, Interactable target) {
605 if (source.movement.needsPlacement())
return;
607 List<Position> boundaries =
new LinkedList<>();
608 Map<Position, LinkedList<Position>> paths =
new HashMap<>();
609 Position cur = source.getPosition();
611 for (Position position : getBoundaries(target)) {
612 Position delta = getDelta(target.getPosition(), position);
613 int dx = Integer.signum(delta.getX()), dy = Integer.signum(delta.getY());
614 Direction direction = Direction.getDirection(dx, dy);
616 if (direction == Direction.NONE)
619 while (inside(cur, source.width(), source.length(), target.getPosition(), target.width(), target.length())) {
620 if (!TraversalMap.isTraversable(cur, direction, source.width())) {
624 cur = cur.transform(direction.getFaceLocation());
625 LinkedList<Position> list = paths.computeIfAbsent(position, pos -> {
626 boundaries.add(position);
627 return new LinkedList<>();
631 paths.put(position, list);
635 if (boundaries.isEmpty())
return;
637 source.setFixingInside(
true);
638 Position random = boundaries.get(0);
639 source.movement.addPath(
new Path(paths.get(random)));
642 public static Position[] getBoundaries(Interactable interactable) {
644 int width = interactable.width();
645 int length = interactable.length();
646 Position[] boundaries =
new Position[2 * (width + length)];
647 for (
int y = 0; y < length + 2; y++) {
648 for (
int x = 0; x < width + 2; x++) {
649 int xx = x % (width + 1);
650 int yy = y % (length + 1);
651 if (xx == 0 && yy == 0 || xx != 0 && yy != 0)
continue;
652 boundaries[nextSlot++] = interactable.getPosition().transform(x - 1, y - 1, 0);
658 public static Position[] getInnerBoundaries(Position position,
int width,
int length) {
660 Position[] boundaries =
new Position[width * length];
661 for (
int y = 0; y < length; y++) {
662 for (
int x = 0; x < width; x++) {
663 boundaries[nextSlot++] = position.transform(x, y, 0);
669 public static Position[] getInnerBoundaries(Interactable interactable) {
671 int width = interactable.width();
672 int length = interactable.length();
673 Position[] boundaries =
new Position[width * length];
674 for (
int y = 0; y < length; y++) {
675 for (
int x = 0; x < width; x++) {
676 boundaries[nextSlot++] = interactable.getPosition().transform(x, y, 0);
682 public static String formatName(
final String input) {
687 StringBuilder formattedName =
new StringBuilder();
690 String[] words = input.trim().split(
" ");
693 for (String word : words) {
694 if (!word.isEmpty()) {
696 char firstLetter = Character.toUpperCase(word.charAt(0));
697 formattedName.append(firstLetter);
700 if (word.length() > 1) {
701 formattedName.append(word.substring(1));
705 formattedName.append(
" ");
710 return formattedName.toString().trim();
713 public static boolean within(Position source, Position target,
int distance) {
714 Interactable interactableSource = Interactable.create(source);
715 Interactable interactableTarget = Interactable.create(target);
716 return within(interactableSource, interactableTarget, distance);
719 public static String formatText(String s) {
720 for (
int i = 0; i < s.length(); i++) {
722 s = String.format(
"%s%s", Character.toUpperCase(s.charAt(0)),
725 if (!Character.isLetterOrDigit(s.charAt(i))) {
726 if (i + 1 < s.length()) {
727 s = String.format(
"%s%s%s", s.subSequence(0, i + 1),
728 Character.toUpperCase(s.charAt(i + 1)),
733 return s.replace(
"_",
" ");
736 public static boolean within(Interactable source, Interactable target,
int distance) {
737 return within(source.getPosition(), source.width(), source.length(), target.getPosition(), target.width(), target.length(), distance);
740 public static boolean withinOctal(Interactable source, Interactable target,
int distance) {
741 return withinOctal(source.getPosition(), source.width(), source.length(), target.getPosition(), target.width(), target.length(), distance);
744 public static boolean withinOctal(Position source,
int sourceWidth,
int sourceLength, Position target,
int targetWidth,
int targetLength,
int distance) {
745 if (target.getHeight() != source.getHeight()) {
748 Position sourceTopRight = source.transform(sourceWidth - 1, sourceLength - 1);
749 Position targetTopRight = target.transform(targetWidth - 1, targetLength - 1);
751 if (sourceTopRight.getX() < target.getX()) {
752 dx = Math.abs(target.getX() - sourceTopRight.getX());
753 }
else if (source.getX() > targetTopRight.getX()) {
754 dx = Math.abs(targetTopRight.getX() - source.getX());
758 if (sourceTopRight.getY() < target.getY()) {
759 dy = Math.abs(target.getY() - sourceTopRight.getY());
760 }
else if (source.getY() > targetTopRight.getY()) {
761 dy = Math.abs(targetTopRight.getY() - source.getY());
765 return dx <= distance && dy <= distance;
768 public static boolean within(Position source,
int sourceWidth,
int sourceLength, Position target,
int targetWidth,
int targetLength,
int distance) {
769 if (target.getHeight() != source.getHeight()) {
772 Position sourceTopRight = source.transform(sourceWidth - 1, sourceLength - 1);
773 Position targetTopRight = target.transform(targetWidth - 1, targetLength - 1);
775 if (sourceTopRight.getX() < target.getX()) {
776 dx = Math.abs(target.getX() - sourceTopRight.getX());
777 }
else if (source.getX() > targetTopRight.getX()) {
778 dx = Math.abs(targetTopRight.getX() - source.getX());
782 if (sourceTopRight.getY() < target.getY()) {
783 dy = Math.abs(target.getY() - sourceTopRight.getY());
784 }
else if (source.getY() > targetTopRight.getY()) {
785 dy = Math.abs(targetTopRight.getY() - source.getY());
789 return dx + dy <= distance;
792 public static boolean withinViewingDistance(Interactable source, Interactable target,
int radius) {
793 if (source ==
null || target ==
null) {
797 if (target.getHeight() != source.getHeight()) {
800 Position sourceTopRight = source.getPosition().transform(source.width() - 1, source.length() - 1);
801 Position targetTopRight = target.getPosition().transform(target.width() - 1, target.length() - 1);
803 if (sourceTopRight.getX() < target.getX()) {
804 dx = Math.abs(target.getX() - sourceTopRight.getX());
805 }
else if (source.getX() > targetTopRight.getX()) {
806 dx = Math.abs(targetTopRight.getX() - source.getX());
810 if (sourceTopRight.getY() < target.getY()) {
811 dy = Math.abs(target.getY() - sourceTopRight.getY());
812 }
else if (source.getY() > targetTopRight.getY()) {
813 dy = Math.abs(targetTopRight.getY() - source.getY());
817 return dx <= radius && dy <= radius;
820 public static boolean inside(Interactable source, Interactable target) {
821 return inside(source.getPosition(), source.width(), source.length(), target.getPosition(), target.width(), target.length());
824 public static boolean inside(Interactable source, Position target) {
825 return inside(source.getPosition(), source.width(), source.length(), target, 1, 1);
828 public static boolean inside(Position source,
int sourceWidth,
int sourceLength, Position target,
int targetWidth,
int targetLength) {
829 if (sourceWidth <= 0) sourceWidth = 1;
830 if (sourceLength <= 0) sourceLength = 1;
831 if (targetWidth <= 0) targetWidth = 1;
832 if (targetLength <= 0) targetLength = 1;
833 Position sourceTopRight = source.transform(sourceWidth - 1, sourceLength - 1, 0);
834 Position targetTopRight = target.transform(targetWidth - 1, targetLength - 1, 0);
835 if (source.equals(target) || sourceTopRight.equals(targetTopRight)) {
838 if (source.getX() > targetTopRight.getX() || sourceTopRight.getX() < target.getX()) {
841 return source.getY() <= targetTopRight.getY() && sourceTopRight.getY() >= target.getY();
844 public static boolean checkRequirements(Player player,
int[] requirements, String action) {
846 for (
int index = 0; index < requirements.length; index++) {
847 int level = player.skills.getMaxLevel(index);
848 int required = requirements[index];
850 if (level < required) {
851 player.send(
new SendMessage(
"You need a level of " + required +
" " + Skill.getName(index) +
" to " + action));
858 public static boolean isLarger(Interactable source, Interactable other) {
859 return source.width() * source.length() > other.width() * other.length();
862 public static int getStarters(String host) {
865 File file =
new File(
"./data/starters/" + host +
".txt");
866 if (!file.exists()) {
869 BufferedReader in =
new BufferedReader(
new FileReader(file));
871 String whatever = in.readLine();
873 long max = Long.parseLong(whatever);
875 if (max > Integer.MAX_VALUE) {
882 }
catch (Exception e) {
888 public static boolean setStarter(Player player) {
889 String host = player.lastHost;
891 int amount = getStarters(host);
899 }
else if (amount == 1) {
904 File file =
new File(
"./data/starters/" + host +
".txt");
905 BufferedWriter out =
new BufferedWriter(
new FileWriter(file,
false));
906 out.write(String.valueOf(amount));
908 }
catch (Exception e) {
915 public static int[] shuffleArray(
int[] array) {
916 int[] shuffledArray =
new int[array.length];
917 System.arraycopy(array, 0, shuffledArray, 0, array.length);
919 for (
int i = shuffledArray.length - 1; i > 0; i--) {
920 int index = RANDOM.nextInt(i + 1);
921 int a = shuffledArray[index];
922 shuffledArray[index] = shuffledArray[i];
923 shuffledArray[i] = a;
925 return shuffledArray;
928 public static int getCurrentDay() {
929 return Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
932 public static int min(
int... values) {
933 int i = Integer.MAX_VALUE;
940 public static final boolean goodDistance(
int objectX,
int objectY,
int playerX,
int playerY,
int distance) {
941 int deltaX = objectX - playerX;
942 int deltaY = objectY - playerY;
943 int trueDistance = ((int) Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)));
944 return trueDistance <= distance;
947 public static boolean inRange(
int absX,
int absY,
int size,
int targetX,
int targetY,
int targetSize,
int distance) {
948 if (absX < targetX) {
952 int closestX = absX + (size - 1);
953 int diffX = targetX - closestX;
954 if (diffX > distance)
956 }
else if (absX > targetX) {
960 int closestTargetX = targetX + (targetSize - 1);
961 int diffX = absX - closestTargetX;
962 if (diffX > distance)
965 if (absY < targetY) {
969 int closestY = absY + (size - 1);
970 int diffY = targetY - closestY;
971 return diffY <= distance;
972 }
else if (absY > targetY) {
976 int closestTargetY = targetY + (targetSize - 1);
977 int diffY = absY - closestTargetY;
978 return diffY <= distance;
983 public static boolean inRange(Interactable source, Interactable target,
int distance) {
984 return inRange(source.getX(), source.getY(), source.width(), target.getX(), target.getY(), target.width(), distance);