callable) {
647 | super(chartId);
648 | this.callable = callable;
649 | }
650 |
651 | @Override
652 | protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
653 | int value = callable.call();
654 | if (value == 0) {
655 | // Null = skip the chart
656 | return null;
657 | }
658 | return new JsonObjectBuilder().appendField("value", value).build();
659 | }
660 | }
661 |
662 | /**
663 | * An extremely simple JSON builder.
664 | *
665 | * While this class is neither feature-rich nor the most performant one, it's sufficient enough
666 | * for its use-case.
667 | */
668 | public static class JsonObjectBuilder {
669 |
670 | private StringBuilder builder = new StringBuilder();
671 |
672 | private boolean hasAtLeastOneField = false;
673 |
674 | public JsonObjectBuilder() {
675 | builder.append("{");
676 | }
677 |
678 | /**
679 | * Appends a null field to the JSON.
680 | *
681 | * @param key The key of the field.
682 | * @return A reference to this object.
683 | */
684 | public JsonObjectBuilder appendNull(String key) {
685 | appendFieldUnescaped(key, "null");
686 | return this;
687 | }
688 |
689 | /**
690 | * Appends a string field to the JSON.
691 | *
692 | * @param key The key of the field.
693 | * @param value The value of the field.
694 | * @return A reference to this object.
695 | */
696 | public JsonObjectBuilder appendField(String key, String value) {
697 | if (value == null) {
698 | throw new IllegalArgumentException("JSON value must not be null");
699 | }
700 | appendFieldUnescaped(key, "\"" + escape(value) + "\"");
701 | return this;
702 | }
703 |
704 | /**
705 | * Appends an integer field to the JSON.
706 | *
707 | * @param key The key of the field.
708 | * @param value The value of the field.
709 | * @return A reference to this object.
710 | */
711 | public JsonObjectBuilder appendField(String key, int value) {
712 | appendFieldUnescaped(key, String.valueOf(value));
713 | return this;
714 | }
715 |
716 | /**
717 | * Appends an object to the JSON.
718 | *
719 | * @param key The key of the field.
720 | * @param object The object.
721 | * @return A reference to this object.
722 | */
723 | public JsonObjectBuilder appendField(String key, JsonObject object) {
724 | if (object == null) {
725 | throw new IllegalArgumentException("JSON object must not be null");
726 | }
727 | appendFieldUnescaped(key, object.toString());
728 | return this;
729 | }
730 |
731 | /**
732 | * Appends a string array to the JSON.
733 | *
734 | * @param key The key of the field.
735 | * @param values The string array.
736 | * @return A reference to this object.
737 | */
738 | public JsonObjectBuilder appendField(String key, String[] values) {
739 | if (values == null) {
740 | throw new IllegalArgumentException("JSON values must not be null");
741 | }
742 | String escapedValues =
743 | Arrays.stream(values)
744 | .map(value -> "\"" + escape(value) + "\"")
745 | .collect(Collectors.joining(","));
746 | appendFieldUnescaped(key, "[" + escapedValues + "]");
747 | return this;
748 | }
749 |
750 | /**
751 | * Appends an integer array to the JSON.
752 | *
753 | * @param key The key of the field.
754 | * @param values The integer array.
755 | * @return A reference to this object.
756 | */
757 | public JsonObjectBuilder appendField(String key, int[] values) {
758 | if (values == null) {
759 | throw new IllegalArgumentException("JSON values must not be null");
760 | }
761 | String escapedValues =
762 | Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
763 | appendFieldUnescaped(key, "[" + escapedValues + "]");
764 | return this;
765 | }
766 |
767 | /**
768 | * Appends an object array to the JSON.
769 | *
770 | * @param key The key of the field.
771 | * @param values The integer array.
772 | * @return A reference to this object.
773 | */
774 | public JsonObjectBuilder appendField(String key, JsonObject[] values) {
775 | if (values == null) {
776 | throw new IllegalArgumentException("JSON values must not be null");
777 | }
778 | String escapedValues =
779 | Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
780 | appendFieldUnescaped(key, "[" + escapedValues + "]");
781 | return this;
782 | }
783 |
784 | /**
785 | * Appends a field to the object.
786 | *
787 | * @param key The key of the field.
788 | * @param escapedValue The escaped value of the field.
789 | */
790 | private void appendFieldUnescaped(String key, String escapedValue) {
791 | if (builder == null) {
792 | throw new IllegalStateException("JSON has already been built");
793 | }
794 | if (key == null) {
795 | throw new IllegalArgumentException("JSON key must not be null");
796 | }
797 | if (hasAtLeastOneField) {
798 | builder.append(",");
799 | }
800 | builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
801 | hasAtLeastOneField = true;
802 | }
803 |
804 | /**
805 | * Builds the JSON string and invalidates this builder.
806 | *
807 | * @return The built JSON string.
808 | */
809 | public JsonObject build() {
810 | if (builder == null) {
811 | throw new IllegalStateException("JSON has already been built");
812 | }
813 | JsonObject object = new JsonObject(builder.append("}").toString());
814 | builder = null;
815 | return object;
816 | }
817 |
818 | /**
819 | * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
820 | *
821 | *
This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
822 | * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
823 | *
824 | * @param value The value to escape.
825 | * @return The escaped value.
826 | */
827 | private static String escape(String value) {
828 | final StringBuilder builder = new StringBuilder();
829 | for (int i = 0; i < value.length(); i++) {
830 | char c = value.charAt(i);
831 | if (c == '"') {
832 | builder.append("\\\"");
833 | } else if (c == '\\') {
834 | builder.append("\\\\");
835 | } else if (c <= '\u000F') {
836 | builder.append("\\u000").append(Integer.toHexString(c));
837 | } else if (c <= '\u001F') {
838 | builder.append("\\u00").append(Integer.toHexString(c));
839 | } else {
840 | builder.append(c);
841 | }
842 | }
843 | return builder.toString();
844 | }
845 |
846 | /**
847 | * A super simple representation of a JSON object.
848 | *
849 | *
This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
850 | * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
851 | * JsonObject)}.
852 | */
853 | public static class JsonObject {
854 |
855 | private final String value;
856 |
857 | private JsonObject(String value) {
858 | this.value = value;
859 | }
860 |
861 | @Override
862 | public String toString() {
863 | return value;
864 | }
865 | }
866 | }
867 | }
--------------------------------------------------------------------------------
/src/main/java/dev/unnm3d/loadingscreenremover/PlayerListener.java:
--------------------------------------------------------------------------------
1 | package dev.unnm3d.loadingscreenremover;
2 |
3 | import com.github.retrooper.packetevents.event.SimplePacketListenerAbstract;
4 | import com.github.retrooper.packetevents.event.simple.PacketPlaySendEvent;
5 | import com.github.retrooper.packetevents.protocol.packettype.PacketType;
6 | import lombok.AllArgsConstructor;
7 | import org.bukkit.entity.Player;
8 | import org.bukkit.event.EventHandler;
9 | import org.bukkit.event.Listener;
10 | import org.bukkit.event.player.PlayerTeleportEvent;
11 |
12 | @AllArgsConstructor
13 | public class PlayerListener extends SimplePacketListenerAbstract implements Listener {
14 | private final LoadingScreenRemover plugin;
15 |
16 | @EventHandler
17 | public void onPlayerTeleportWorld(PlayerTeleportEvent event) {
18 | if (event.getFrom().getWorld() == null || event.getTo().getWorld() == null) return;
19 |
20 | // If the player is changing worlds, and the environments are the same
21 | if (event.getFrom().getWorld() != event.getTo().getWorld() &&
22 | event.getFrom().getWorld().getEnvironment() == event.getTo().getWorld().getEnvironment()) {
23 | plugin.getPlayerManager().addChangingWorldPlayer(event.getPlayer());
24 | }else return;
25 | plugin.getTaskScheduler().runTaskLater(() -> plugin.getPlayerManager().removeChangingWorldPlayer(event.getPlayer()), 2);
26 | }
27 |
28 | @Override
29 | public void onPacketPlaySend(PacketPlaySendEvent event) {
30 | if (event.getPacketType() != PacketType.Play.Server.RESPAWN) {
31 | return;
32 | }
33 |
34 | if (plugin.getPlayerManager().isPlayerChangingWorlds(event.getPlayer())) {
35 | event.setCancelled(true);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/dev/unnm3d/loadingscreenremover/PlayerManager.java:
--------------------------------------------------------------------------------
1 | package dev.unnm3d.loadingscreenremover;
2 |
3 | import org.bukkit.entity.Player;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.Set;
7 | import java.util.concurrent.ConcurrentHashMap;
8 |
9 | public class PlayerManager {
10 | private final Set changingWorlds = ConcurrentHashMap.newKeySet();
11 |
12 | public boolean isPlayerChangingWorlds(@NotNull Player player) {
13 | return changingWorlds.contains(player);
14 | }
15 |
16 | public void addChangingWorldPlayer(@NotNull Player player) {
17 | changingWorlds.add(player);
18 | }
19 |
20 | public void removeChangingWorldPlayer(@NotNull Player player) {
21 | changingWorlds.remove(player);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: LoadingScreenRemover
2 | version: '${version}'
3 | author: Unnm3d
4 | main: dev.unnm3d.loadingscreenremover.LoadingScreenRemover
5 | api-version: '1.18'
6 | folia-supported: true
7 |
--------------------------------------------------------------------------------