resetLore = new ArrayList<>();
94 | resetLore.add("");
95 | resetLore.add("&7Would you like to reset");
96 | resetLore.add("&7The Resource World?");
97 | ItemStack reset = makeItem(Material.EMERALD, 1, "&aReset", resetLore);
98 |
99 | inventory.setItem(13, teleport);
100 | inventory.setItem(15, reload);
101 | inventory.setItem(30, support);
102 | inventory.setItem(32, reset);
103 | inventory.setItem(49, exit);
104 | }
105 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/gui/menus/WorldsGui.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.gui.menus;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.api.ResourceWorldType;
5 | import me.nik.resourceworld.gui.Menu;
6 | import me.nik.resourceworld.gui.PlayerMenu;
7 | import me.nik.resourceworld.managers.MsgType;
8 | import org.bukkit.Material;
9 | import org.bukkit.entity.Player;
10 | import org.bukkit.event.inventory.InventoryClickEvent;
11 | import org.bukkit.inventory.ItemStack;
12 |
13 | public class WorldsGui extends Menu {
14 | public WorldsGui(PlayerMenu playerMenu, ResourceWorld plugin) {
15 | super(playerMenu, plugin);
16 | }
17 |
18 | @Override
19 | protected String getMenuName() {
20 | return MsgType.WORLDS_GUI_NAME.getMessage();
21 | }
22 |
23 | @Override
24 | protected int getSlots() {
25 | return 36;
26 | }
27 |
28 | @Override
29 | public void handleMenu(InventoryClickEvent e) {
30 | Player p = (Player) e.getWhoClicked();
31 | switch (e.getSlot()) {
32 | case 13:
33 | this.plugin.getResourceWorld(ResourceWorldType.RESOURCE_WORLD).reset();
34 | p.closeInventory();
35 | break;
36 | case 11:
37 | this.plugin.getResourceWorld(ResourceWorldType.RESOURCE_NETHER).reset();
38 | p.closeInventory();
39 | break;
40 | case 15:
41 | this.plugin.getResourceWorld(ResourceWorldType.RESOURCE_END).reset();
42 | p.closeInventory();
43 | break;
44 | case 31:
45 | p.closeInventory();
46 | new MainGui(playerMenu, plugin).open();
47 | break;
48 | }
49 | }
50 |
51 | @Override
52 | protected void setMenuItems() {
53 | ItemStack resource = makeItem(Material.DIRT, 1, "&aResource World", null);
54 | ItemStack nether = makeItem(Material.NETHERRACK, 1, "&cNether World", null);
55 | ItemStack end = makeItem(Material.OBSIDIAN, 1, "&9End World", null);
56 | ItemStack back = makeItem(Material.BARRIER, 1, "&cBack", null);
57 |
58 | inventory.setItem(11, nether);
59 | inventory.setItem(13, resource);
60 | inventory.setItem(15, end);
61 | inventory.setItem(31, back);
62 | }
63 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/managers/MsgType.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.managers;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.utils.ChatUtils;
5 |
6 | public enum MsgType {
7 | PREFIX(ChatUtils.format(ResourceWorld.getInstance().getLang().getString("prefix"))),
8 | UPDATE_FOUND(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("update_found"))),
9 | DISABLED_COMMAND(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("disabled_command"))),
10 | RESETTING_THE_WORLD(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("resetting_the_world"))),
11 | RESETTING_THE_NETHER(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("resetting_the_nether"))),
12 | RESETTING_THE_END(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("resetting_the_end"))),
13 | WORLD_HAS_BEEN_RESET(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("world_has_been_reset"))),
14 | NETHER_HAS_BEEN_RESET(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("nether_has_been_reset"))),
15 | END_HAS_BEEN_RESET(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("end_has_been_reset"))),
16 | CONSOLE_MESSAGE(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("console_message"))),
17 | NO_PERMISSION(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("no_perm"))),
18 | COOLDOWN_MESSAGE(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("cooldown_message"))),
19 | RELOADED(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("reloaded"))),
20 | TELEPORT_DELAY(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("teleport_delay"))),
21 | GUI_NAME(ChatUtils.format(ResourceWorld.getInstance().getLang().getString("gui_name"))),
22 | WORLDS_GUI_NAME(ChatUtils.format(ResourceWorld.getInstance().getLang().getString("worlds_gui_name"))),
23 | TELEPORTED_MESSAGE(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("teleported_message"))),
24 | NOT_EXIST(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("not_exist"))),
25 | TELEPORT_PAID(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("teleport_paid"))),
26 | TELEPORT_ERROR(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("teleport_error"))),
27 | TELEPORTED_PLAYERS(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("teleported_players"))),
28 | UPDATE_NOT_FOUND(PREFIX.getMessage() + ChatUtils.format(ResourceWorld.getInstance().getLang().getString("update_not_found")));
29 |
30 | private final String message;
31 |
32 | MsgType(String message) {
33 | this.message = message;
34 | }
35 |
36 | public String getMessage() {
37 | return message;
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/managers/PapiHook.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.managers;
2 |
3 | import me.clip.placeholderapi.expansion.PlaceholderExpansion;
4 | import me.nik.resourceworld.ResourceWorld;
5 | import me.nik.resourceworld.files.Config;
6 | import me.nik.resourceworld.utils.MiscUtils;
7 | import org.bukkit.OfflinePlayer;
8 |
9 | public class PapiHook extends PlaceholderExpansion {
10 |
11 | private final ResourceWorld plugin;
12 |
13 | public PapiHook(ResourceWorld plugin) {
14 | this.plugin = plugin;
15 | }
16 |
17 | @Override
18 | public String getIdentifier() {
19 | return "rw";
20 | }
21 |
22 | @Override
23 | public String getAuthor() {
24 | return plugin.getDescription().getAuthors().toString();
25 | }
26 |
27 | @Override
28 | public String getVersion() {
29 | return plugin.getDescription().getVersion();
30 | }
31 |
32 | @Override
33 | public boolean canRegister() {
34 | return true;
35 | }
36 |
37 | @Override
38 | public boolean persist() {
39 | return true;
40 | }
41 |
42 | @Override
43 | public String onRequest(OfflinePlayer player, String identifier) {
44 |
45 | switch (identifier) {
46 | case "world":
47 | if (!Config.Setting.WORLD_ENABLED.getBoolean() && !Config.Setting.WORLD_RESETS_ENABLED.getBoolean())
48 | return "";
49 | if (Config.Setting.WORLD_STORE_TIME.getBoolean()) {
50 | return MiscUtils.getDurationBreakdown((Config.Setting.WORLD_RESETS_INTERVAL.getInt() * 3600000L + plugin.getData().getLong("world.millis")) - System.currentTimeMillis());
51 | } else {
52 | return MiscUtils.getDurationBreakdown((Config.Setting.WORLD_RESETS_INTERVAL.getInt() * 3600000L + plugin.getData().getLong("world.papi")) - System.currentTimeMillis());
53 | }
54 | case "nether":
55 | if (!Config.Setting.NETHER_ENABLED.getBoolean() && !Config.Setting.NETHER_RESETS_ENABLED.getBoolean())
56 | return "";
57 | if (Config.Setting.NETHER_STORE_TIME.getBoolean()) {
58 | return MiscUtils.getDurationBreakdown((Config.Setting.NETHER_RESETS_INTERVAL.getInt() * 3600000L + plugin.getData().getLong("nether.millis")) - System.currentTimeMillis());
59 | } else {
60 | return MiscUtils.getDurationBreakdown((Config.Setting.NETHER_RESETS_INTERVAL.getInt() * 3600000L + plugin.getData().getLong("nether.papi")) - System.currentTimeMillis());
61 | }
62 | case "end":
63 | if (!Config.Setting.END_ENABLED.getBoolean() && !Config.Setting.END_RESETS_ENABLED.getBoolean())
64 | return "";
65 | if (Config.Setting.END_STORE_TIME.getBoolean()) {
66 | return MiscUtils.getDurationBreakdown((Config.Setting.END_RESETS_INTERVAL.getInt() * 3600000L + plugin.getData().getLong("end.millis")) - System.currentTimeMillis());
67 | } else {
68 | return MiscUtils.getDurationBreakdown((Config.Setting.END_RESETS_INTERVAL.getInt() * 3600000L + plugin.getData().getLong("end.papi")) - System.currentTimeMillis());
69 | }
70 | }
71 | return null;
72 | }
73 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/managers/Permissions.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.managers;
2 |
3 | public enum Permissions {
4 | ADMIN("rw.admin"),
5 | TELEPORT("rw.tp"),
6 | TELEPORT_NETHER("rw.tp.nether"),
7 | TELEPORT_END("rw.tp.end");
8 |
9 | private final String permission;
10 |
11 | Permissions(String permission) {
12 | this.permission = permission;
13 | }
14 |
15 | public String getPermission() {
16 | return this.permission;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/managers/UpdateChecker.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.managers;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.utils.ChatUtils;
5 | import org.bukkit.Bukkit;
6 | import org.bukkit.entity.Player;
7 | import org.bukkit.event.EventHandler;
8 | import org.bukkit.event.EventPriority;
9 | import org.bukkit.event.Listener;
10 | import org.bukkit.event.player.PlayerJoinEvent;
11 | import org.bukkit.scheduler.BukkitRunnable;
12 |
13 | import java.io.BufferedReader;
14 | import java.io.IOException;
15 | import java.io.InputStreamReader;
16 | import java.net.URL;
17 | import java.net.URLConnection;
18 |
19 | public class UpdateChecker extends BukkitRunnable implements Listener {
20 |
21 | private final ResourceWorld plugin;
22 | private String newVersion;
23 |
24 | public UpdateChecker(ResourceWorld plugin) {
25 | this.plugin = plugin;
26 | }
27 |
28 | @Override
29 | public void run() {
30 |
31 | try {
32 |
33 | URLConnection connection = new URL("https://raw.githubusercontent.com/NikV2/ResourceWorld/master/version.txt").openConnection();
34 |
35 | connection.addRequestProperty("User-Agent", "Mozilla/4.0");
36 |
37 | BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
38 |
39 | this.newVersion = reader.readLine();
40 |
41 | reader.close();
42 |
43 | } catch (IOException e) {
44 | ChatUtils.consoleMessage("Couldn't check for updates, Is the server connected to the internet?");
45 | return;
46 | }
47 |
48 | if (!this.plugin.getDescription().getVersion().equals(this.newVersion)) {
49 |
50 | Bukkit.getServer().getConsoleSender().sendMessage(
51 | MsgType.UPDATE_FOUND.getMessage()
52 | .replace("%current%", this.plugin.getDescription().getVersion())
53 | .replace("%new%", this.newVersion)
54 | );
55 |
56 | Bukkit.getPluginManager().registerEvents(this, this.plugin);
57 |
58 | } else Bukkit.getServer().getConsoleSender().sendMessage(MsgType.UPDATE_NOT_FOUND.getMessage());
59 | }
60 |
61 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
62 | public void onJoin(PlayerJoinEvent e) {
63 |
64 | Player player = e.getPlayer();
65 |
66 | if (player.hasPermission(Permissions.ADMIN.getPermission())) {
67 |
68 | player.sendMessage(MsgType.UPDATE_FOUND.getMessage()
69 | .replace("%current%", this.plugin.getDescription().getVersion())
70 | .replace("%new%", this.newVersion));
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/managers/custom/CustomWorld.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.managers.custom;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.api.ResourceWorldType;
5 | import me.nik.resourceworld.files.Config;
6 | import me.nik.resourceworld.managers.MsgType;
7 | import me.nik.resourceworld.utils.ChatUtils;
8 | import me.nik.resourceworld.utils.MiscUtils;
9 | import me.nik.resourceworld.utils.TaskUtils;
10 | import org.bukkit.Bukkit;
11 | import org.bukkit.Difficulty;
12 | import org.bukkit.GameRule;
13 | import org.bukkit.World;
14 | import org.bukkit.WorldBorder;
15 | import org.bukkit.WorldCreator;
16 | import org.bukkit.WorldType;
17 | import org.bukkit.event.EventHandler;
18 | import org.bukkit.event.EventPriority;
19 | import org.bukkit.event.HandlerList;
20 | import org.bukkit.event.Listener;
21 | import org.bukkit.event.player.PlayerTeleportEvent;
22 |
23 | public class CustomWorld implements Listener {
24 |
25 | private final ResourceWorldType resourceWorldType;
26 | private final String name;
27 | private final Difficulty difficulty;
28 | private final WorldType type;
29 | private final World.Environment environment;
30 | private final boolean structures;
31 | private final boolean useSeed;
32 | private final long seed;
33 | private final boolean useBorder;
34 | private final int borderSize;
35 | private final boolean pvp;
36 | private final boolean keepInventory;
37 |
38 | public CustomWorld(String name, Difficulty difficulty, WorldType type, World.Environment environment, boolean structures, boolean useSeed, long seed, boolean useBorder, int borderSize, boolean pvp, boolean keepInventory, ResourceWorldType resourceWorldType) {
39 | this.name = name;
40 | this.difficulty = difficulty;
41 | this.type = type;
42 | this.environment = environment;
43 | this.structures = structures;
44 | this.useSeed = useSeed;
45 | this.seed = seed;
46 | this.useBorder = useBorder;
47 | this.borderSize = borderSize;
48 | this.pvp = pvp;
49 | this.keepInventory = keepInventory;
50 | this.resourceWorldType = resourceWorldType;
51 | }
52 |
53 | public String getName() {
54 | return name;
55 | }
56 |
57 | public CustomWorld generate() {
58 |
59 | WorldCreator wc = new WorldCreator(this.name);
60 |
61 | wc.type(this.type);
62 |
63 | wc.generateStructures(this.structures);
64 |
65 | wc.environment(this.environment);
66 |
67 | if (this.useSeed) wc.seed(this.seed);
68 |
69 | wc.createWorld();
70 |
71 | World rw = Bukkit.getWorld(this.name);
72 |
73 | if (this.useBorder) {
74 |
75 | WorldBorder wb = rw.getWorldBorder();
76 |
77 | wb.setCenter(0, 0);
78 |
79 | wb.setSize(this.borderSize);
80 |
81 | }
82 |
83 | rw.setPVP(this.pvp);
84 |
85 | rw.setDifficulty(this.difficulty);
86 |
87 | Bukkit.getWorlds().add(rw);
88 |
89 | if (!MiscUtils.isLegacy() && this.keepInventory) rw.setGameRule(GameRule.KEEP_INVENTORY, true);
90 |
91 | return this;
92 | }
93 |
94 | public void reset() {
95 |
96 | ChatUtils.consoleMessage("Executing world reset...");
97 |
98 | //Phase 1
99 |
100 | World world = Bukkit.getWorld(this.name);
101 |
102 | if (world == null) return;
103 |
104 | Bukkit.getOnlinePlayers().stream().filter(player -> player.getWorld().getUID().equals(world.getUID())).forEach(player -> {
105 |
106 | player.teleport(Bukkit.getWorld(Config.Setting.SETTINGS_SPAWN_WORLD.getString()).getSpawnLocation());
107 |
108 | player.sendMessage(MsgType.TELEPORTED_MESSAGE.getMessage());
109 | });
110 |
111 | ResourceWorld plugin = ResourceWorld.getInstance();
112 |
113 | Bukkit.getPluginManager().registerEvents(this, plugin);
114 |
115 | ChatUtils.consoleMessage("Phase 1 completed...");
116 |
117 | //Phase 2
118 | TaskUtils.taskLater(() -> {
119 |
120 | switch (this.resourceWorldType) {
121 |
122 | case RESOURCE_END:
123 |
124 | Bukkit.broadcastMessage(MsgType.RESETTING_THE_END.getMessage());
125 |
126 | if (Config.Setting.END_STORE_TIME.getBoolean()) {
127 | plugin.getData().set("end.millis", System.currentTimeMillis());
128 | }
129 |
130 | plugin.getData().set("end.papi", System.currentTimeMillis());
131 |
132 | break;
133 |
134 | case RESOURCE_WORLD:
135 |
136 | Bukkit.broadcastMessage(MsgType.RESETTING_THE_WORLD.getMessage());
137 |
138 | if (Config.Setting.WORLD_STORE_TIME.getBoolean()) {
139 | plugin.getData().set("world.millis", System.currentTimeMillis());
140 | }
141 |
142 | plugin.getData().set("world.papi", System.currentTimeMillis());
143 |
144 | break;
145 |
146 | case RESOURCE_NETHER:
147 |
148 | Bukkit.broadcastMessage(MsgType.RESETTING_THE_NETHER.getMessage());
149 |
150 | if (Config.Setting.NETHER_STORE_TIME.getBoolean()) {
151 | plugin.getData().set("nether.millis", System.currentTimeMillis());
152 | }
153 |
154 | plugin.getData().set("nether.papi", System.currentTimeMillis());
155 |
156 | break;
157 | }
158 |
159 | plugin.saveData();
160 | plugin.reloadData();
161 | plugin.saveData();
162 |
163 | Bukkit.unloadWorld(world, false);
164 |
165 | MiscUtils.deleteDirectory(world.getWorldFolder());
166 |
167 | ChatUtils.consoleMessage("Phase 2 completed...");
168 |
169 | //Phase 3
170 | TaskUtils.taskLater(() -> {
171 |
172 | generate();
173 |
174 | ChatUtils.consoleMessage("Phase 3 completed...");
175 |
176 | //Phase 4
177 | TaskUtils.taskLater(() -> {
178 |
179 | switch (this.resourceWorldType) {
180 |
181 | case RESOURCE_END:
182 |
183 | if (Config.Setting.END_COMMANDS_ENABLED.getBoolean()) {
184 |
185 | for (String cmd : Config.Setting.END_COMMANDS_COMMANDS.getStringList()) {
186 |
187 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
188 | }
189 | }
190 |
191 | Bukkit.broadcastMessage(MsgType.END_HAS_BEEN_RESET.getMessage());
192 |
193 | break;
194 |
195 | case RESOURCE_WORLD:
196 | if (Config.Setting.WORLD_COMMANDS_ENABLED.getBoolean()) {
197 | for (String cmd : Config.Setting.WORLD_COMMANDS_COMMANDS.getStringList()) {
198 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
199 | }
200 | }
201 |
202 | Bukkit.broadcastMessage(MsgType.WORLD_HAS_BEEN_RESET.getMessage());
203 |
204 | break;
205 | case RESOURCE_NETHER:
206 |
207 | if (Config.Setting.NETHER_COMMANDS_ENABLED.getBoolean()) {
208 |
209 | for (String cmd : Config.Setting.NETHER_COMMANDS_COMMANDS.getStringList()) {
210 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
211 | }
212 | }
213 |
214 | Bukkit.broadcastMessage(MsgType.NETHER_HAS_BEEN_RESET.getMessage());
215 |
216 | break;
217 | }
218 |
219 | HandlerList.unregisterAll(this);
220 |
221 | ChatUtils.consoleMessage("All phases completed!");
222 |
223 | }, 160L);
224 |
225 | }, 80L);
226 |
227 | }, 80L);
228 | }
229 |
230 | @EventHandler(priority = EventPriority.LOWEST)
231 | public void onWorldTeleport(PlayerTeleportEvent e) {
232 | if (e.getTo().getWorld().getName().equals(this.name)) e.setCancelled(true);
233 | }
234 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/managers/custom/ResourceWorldException.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.managers.custom;
2 |
3 | public class ResourceWorldException extends RuntimeException {
4 | public ResourceWorldException(String message) {
5 | super(message);
6 | }
7 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/metrics/MetricsLite.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.metrics;
2 |
3 | import com.google.gson.JsonArray;
4 | import com.google.gson.JsonObject;
5 | import com.google.gson.JsonParser;
6 | import org.bukkit.Bukkit;
7 | import org.bukkit.configuration.file.YamlConfiguration;
8 | import org.bukkit.entity.Player;
9 | import org.bukkit.plugin.Plugin;
10 | import org.bukkit.plugin.RegisteredServiceProvider;
11 | import org.bukkit.plugin.ServicePriority;
12 |
13 | import javax.net.ssl.HttpsURLConnection;
14 | import java.io.BufferedReader;
15 | import java.io.ByteArrayOutputStream;
16 | import java.io.DataOutputStream;
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.io.InputStreamReader;
20 | import java.lang.reflect.InvocationTargetException;
21 | import java.lang.reflect.Method;
22 | import java.net.URL;
23 | import java.nio.charset.StandardCharsets;
24 | import java.util.Collection;
25 | import java.util.Timer;
26 | import java.util.TimerTask;
27 | import java.util.UUID;
28 | import java.util.logging.Level;
29 | import java.util.zip.GZIPOutputStream;
30 |
31 | /**
32 | * bStats collects some data for plugin authors.
33 | *
34 | * Check out https://bStats.org/ to learn more about bStats!
35 | */
36 | @SuppressWarnings({"WeakerAccess", "unused"})
37 | public class MetricsLite {
38 |
39 | // The version of this bStats class
40 | public static final int B_STATS_VERSION = 1;
41 | // The url to which the data is sent
42 | private static final String URL = "https://bStats.org/submitData/bukkit";
43 | // Should failed requests be logged?
44 | private static boolean logFailedRequests;
45 | // Should the sent data be logged?
46 | private static boolean logSentData;
47 | // Should the response text be logged?
48 | private static boolean logResponseStatusText;
49 | // The uuid of the server
50 | private static String serverUUID;
51 |
52 | static {
53 | // You can use the property to disable the check in your test environment
54 | if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
55 | // Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
56 | final String defaultPackage = new String(
57 | new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
58 | final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
59 | // We want to make sure nobody just copy & pastes the example and use the wrong package names
60 | if (MetricsLite.class.getPackage().getName().equals(defaultPackage) || MetricsLite.class.getPackage().getName().equals(examplePackage)) {
61 | throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
62 | }
63 | }
64 | }
65 |
66 | // Is bStats enabled on this server?
67 | private final boolean enabled;
68 | // The plugin
69 | private final Plugin plugin;
70 |
71 | // The plugin id
72 | private final int pluginId;
73 |
74 | /**
75 | * Class constructor.
76 | *
77 | * @param plugin The plugin which stats should be submitted.
78 | * @param pluginId The id of the plugin.
79 | * It can be found at What is my plugin id?
80 | */
81 | public MetricsLite(Plugin plugin, int pluginId) {
82 | if (plugin == null) {
83 | throw new IllegalArgumentException("Plugin cannot be null!");
84 | }
85 | this.plugin = plugin;
86 | this.pluginId = pluginId;
87 |
88 | // Get the config file
89 | File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
90 | File configFile = new File(bStatsFolder, "config.yml");
91 | YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
92 |
93 | // Check if the config file exists
94 | if (!config.isSet("serverUuid")) {
95 |
96 | // Add default values
97 | config.addDefault("enabled", true);
98 | // Every server gets it's unique random id.
99 | config.addDefault("serverUuid", UUID.randomUUID().toString());
100 | // Should failed request be logged?
101 | config.addDefault("logFailedRequests", false);
102 | // Should the sent data be logged?
103 | config.addDefault("logSentData", false);
104 | // Should the response text be logged?
105 | config.addDefault("logResponseStatusText", false);
106 |
107 | // Inform the server owners about bStats
108 | config.options().header(
109 | "bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
110 | "To honor their work, you should not disable it.\n" +
111 | "This has nearly no effect on the server performance!\n" +
112 | "Check out https://bStats.org/ to learn more :)"
113 | ).copyDefaults(true);
114 | try {
115 | config.save(configFile);
116 | } catch (IOException ignored) {
117 | }
118 | }
119 |
120 | // Load the data
121 | serverUUID = config.getString("serverUuid");
122 | logFailedRequests = config.getBoolean("logFailedRequests", false);
123 | enabled = config.getBoolean("enabled", true);
124 | logSentData = config.getBoolean("logSentData", false);
125 | logResponseStatusText = config.getBoolean("logResponseStatusText", false);
126 | if (enabled) {
127 | boolean found = false;
128 | // Search for all other bStats Metrics classes to see if we are the first one
129 | for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
130 | try {
131 | service.getField("B_STATS_VERSION"); // Our identifier :)
132 | found = true; // We aren't the first
133 | break;
134 | } catch (NoSuchFieldException ignored) {
135 | }
136 | }
137 | // Register our service
138 | Bukkit.getServicesManager().register(MetricsLite.class, this, plugin, ServicePriority.Normal);
139 | if (!found) {
140 | // We are the first!
141 | startSubmitting();
142 | }
143 | }
144 | }
145 |
146 | /**
147 | * Sends the data to the bStats server.
148 | *
149 | * @param plugin Any plugin. It's just used to get a logger instance.
150 | * @param data The data to send.
151 | * @throws Exception If the request failed.
152 | */
153 | private static void sendData(Plugin plugin, JsonObject data) throws Exception {
154 | if (data == null) {
155 | throw new IllegalArgumentException("Data cannot be null!");
156 | }
157 | if (Bukkit.isPrimaryThread()) {
158 | throw new IllegalAccessException("This method must not be called from the main thread!");
159 | }
160 | if (logSentData) {
161 | plugin.getLogger().info("Sending data to bStats: " + data);
162 | }
163 | HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
164 |
165 | // Compress the data to save bandwidth
166 | byte[] compressedData = compress(data.toString());
167 |
168 | // Add headers
169 | connection.setRequestMethod("POST");
170 | connection.addRequestProperty("Accept", "application/json");
171 | connection.addRequestProperty("Connection", "close");
172 | connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
173 | connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
174 | connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
175 | connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
176 |
177 | // Send data
178 | connection.setDoOutput(true);
179 | try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
180 | outputStream.write(compressedData);
181 | }
182 |
183 | StringBuilder builder = new StringBuilder();
184 | try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
185 | String line;
186 | while ((line = bufferedReader.readLine()) != null) {
187 | builder.append(line);
188 | }
189 | }
190 |
191 | if (logResponseStatusText) {
192 | plugin.getLogger().info("Sent data to bStats and received response: " + builder);
193 | }
194 | }
195 |
196 | /**
197 | * Gzips the given String.
198 | *
199 | * @param str The string to gzip.
200 | * @return The gzipped String.
201 | * @throws IOException If the compression failed.
202 | */
203 | private static byte[] compress(final String str) throws IOException {
204 | if (str == null) {
205 | return null;
206 | }
207 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
208 | try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
209 | gzip.write(str.getBytes(StandardCharsets.UTF_8));
210 | }
211 | return outputStream.toByteArray();
212 | }
213 |
214 | /**
215 | * Checks if bStats is enabled.
216 | *
217 | * @return Whether bStats is enabled or not.
218 | */
219 | public boolean isEnabled() {
220 | return enabled;
221 | }
222 |
223 | /**
224 | * Starts the Scheduler which submits our data every 30 minutes.
225 | */
226 | private void startSubmitting() {
227 | final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
228 | timer.scheduleAtFixedRate(new TimerTask() {
229 | @Override
230 | public void run() {
231 | if (!plugin.isEnabled()) { // Plugin was disabled
232 | timer.cancel();
233 | return;
234 | }
235 | // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
236 | // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
237 | Bukkit.getScheduler().runTask(plugin, () -> submitData());
238 | }
239 | }, 1000 * 60 * 5, 1000 * 60 * 30);
240 | // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
241 | // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
242 | // WARNING: Just don't do it!
243 | }
244 |
245 | /**
246 | * Gets the plugin specific data.
247 | * This method is called using Reflection.
248 | *
249 | * @return The plugin specific data.
250 | */
251 | public JsonObject getPluginData() {
252 | JsonObject data = new JsonObject();
253 |
254 | String pluginName = plugin.getDescription().getName();
255 | String pluginVersion = plugin.getDescription().getVersion();
256 |
257 | data.addProperty("pluginName", pluginName); // Append the name of the plugin
258 | data.addProperty("id", pluginId); // Append the id of the plugin
259 | data.addProperty("pluginVersion", pluginVersion); // Append the version of the plugin
260 | data.add("customCharts", new JsonArray());
261 |
262 | return data;
263 | }
264 |
265 | /**
266 | * Gets the server specific data.
267 | *
268 | * @return The server specific data.
269 | */
270 | private JsonObject getServerData() {
271 | // Minecraft specific data
272 | int playerAmount;
273 | try {
274 | // Around MC 1.8 the return type was changed to a collection from an array,
275 | // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
276 | Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
277 | playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
278 | ? ((Collection>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
279 | : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
280 | } catch (Exception e) {
281 | playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
282 | }
283 | int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
284 | String bukkitVersion = Bukkit.getVersion();
285 | String bukkitName = Bukkit.getName();
286 |
287 | // OS/Java specific data
288 | String javaVersion = System.getProperty("java.version");
289 | String osName = System.getProperty("os.name");
290 | String osArch = System.getProperty("os.arch");
291 | String osVersion = System.getProperty("os.version");
292 | int coreCount = Runtime.getRuntime().availableProcessors();
293 |
294 | JsonObject data = new JsonObject();
295 |
296 | data.addProperty("serverUUID", serverUUID);
297 |
298 | data.addProperty("playerAmount", playerAmount);
299 | data.addProperty("onlineMode", onlineMode);
300 | data.addProperty("bukkitVersion", bukkitVersion);
301 | data.addProperty("bukkitName", bukkitName);
302 |
303 | data.addProperty("javaVersion", javaVersion);
304 | data.addProperty("osName", osName);
305 | data.addProperty("osArch", osArch);
306 | data.addProperty("osVersion", osVersion);
307 | data.addProperty("coreCount", coreCount);
308 |
309 | return data;
310 | }
311 |
312 | /**
313 | * Collects the data and sends it afterwards.
314 | */
315 | private void submitData() {
316 | final JsonObject data = getServerData();
317 |
318 | JsonArray pluginData = new JsonArray();
319 | // Search for all other bStats Metrics classes to get their plugin data
320 | for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
321 | try {
322 | service.getField("B_STATS_VERSION"); // Our identifier :)
323 |
324 | for (RegisteredServiceProvider> provider : Bukkit.getServicesManager().getRegistrations(service)) {
325 | try {
326 | Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
327 | if (plugin instanceof JsonObject) {
328 | pluginData.add((JsonObject) plugin);
329 | } else { // old bstats version compatibility
330 | try {
331 | Class> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
332 | if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
333 | Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
334 | jsonStringGetter.setAccessible(true);
335 | String jsonString = (String) jsonStringGetter.invoke(plugin);
336 | JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
337 | pluginData.add(object);
338 | }
339 | } catch (ClassNotFoundException e) {
340 | // minecraft version 1.14+
341 | if (logFailedRequests) {
342 | this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
343 | }
344 | }
345 | }
346 | } catch (NullPointerException | NoSuchMethodException | IllegalAccessException |
347 | InvocationTargetException ignored) {
348 | }
349 | }
350 | } catch (NoSuchFieldException ignored) {
351 | }
352 | }
353 |
354 | data.add("plugins", pluginData);
355 |
356 | // Create a new thread for the connection to the bStats server
357 | new Thread(() -> {
358 | try {
359 | // Send the data
360 | sendData(plugin, data);
361 | } catch (Exception e) {
362 | // Something went wrong! :(
363 | if (logFailedRequests) {
364 | plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
365 | }
366 | }
367 | }).start();
368 | }
369 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/modules/ListenerModule.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.modules;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import org.bukkit.event.HandlerList;
5 | import org.bukkit.event.Listener;
6 |
7 | public abstract class ListenerModule implements Listener {
8 |
9 | protected final ResourceWorld plugin;
10 | private final boolean enabled;
11 |
12 | public ListenerModule(boolean enabled, ResourceWorld plugin) {
13 | this.enabled = enabled;
14 | this.plugin = plugin;
15 | }
16 |
17 | public void load() {
18 | if (!this.enabled) return;
19 | this.plugin.getServer().getPluginManager().registerEvents(this, this.plugin);
20 | }
21 |
22 | public void shutdown() {
23 | if (!this.enabled) return;
24 | HandlerList.unregisterAll(this);
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/modules/impl/DisabledCommands.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.modules.impl;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.files.Config;
5 | import me.nik.resourceworld.managers.MsgType;
6 | import me.nik.resourceworld.managers.Permissions;
7 | import me.nik.resourceworld.modules.ListenerModule;
8 | import org.bukkit.entity.Player;
9 | import org.bukkit.event.EventHandler;
10 | import org.bukkit.event.EventPriority;
11 | import org.bukkit.event.player.PlayerCommandPreprocessEvent;
12 |
13 | import java.util.List;
14 |
15 | public class DisabledCommands extends ListenerModule {
16 |
17 | public DisabledCommands(ResourceWorld plugin) {
18 | super((Config.Setting.WORLD_DISABLED_COMMANDS_ENABLED.getBoolean()
19 | || Config.Setting.NETHER_DISABLED_COMMANDS_ENABLED.getBoolean()
20 | || Config.Setting.END_DISABLED_COMMANDS_ENABLED.getBoolean()), plugin);
21 | }
22 |
23 | @EventHandler(priority = EventPriority.HIGHEST)
24 | public void disableWorldCommands(PlayerCommandPreprocessEvent e) {
25 |
26 | Player player = e.getPlayer();
27 |
28 | if (player.hasPermission(Permissions.ADMIN.getPermission()) || e.getMessage().equals("/")) return;
29 |
30 | String world = player.getWorld().getName();
31 |
32 | String message = e.getMessage();
33 |
34 | if (world.equals(Config.Setting.WORLD_NAME.getString())) {
35 |
36 | e.setCancelled(
37 | Config.Setting.WORLD_DISABLED_COMMANDS_ENABLED.getBoolean()
38 | && isDisabledCommand(Config.Setting.WORLD_DISABLED_COMMANDS_LIST.getStringList(), message)
39 | );
40 |
41 | } else if (world.equals(Config.Setting.NETHER_NAME.getString())) {
42 |
43 | e.setCancelled(
44 | Config.Setting.NETHER_DISABLED_COMMANDS_ENABLED.getBoolean()
45 | && isDisabledCommand(Config.Setting.NETHER_DISABLED_COMMANDS_LIST.getStringList(), message)
46 | );
47 |
48 | } else if (world.equals(Config.Setting.END_NAME.getString())) {
49 |
50 | e.setCancelled(
51 | Config.Setting.END_DISABLED_COMMANDS_ENABLED.getBoolean()
52 | && isDisabledCommand(Config.Setting.END_DISABLED_COMMANDS_LIST.getStringList(), message)
53 | );
54 | }
55 |
56 | if (e.isCancelled()) {
57 | player.sendMessage(MsgType.DISABLED_COMMAND.getMessage());
58 | }
59 | }
60 |
61 | private boolean isDisabledCommand(List list, String cmd) {
62 | return list.stream().anyMatch(cmd::contains);
63 | }
64 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/modules/impl/LeaveWorld.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.modules.impl;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.files.Config;
5 | import me.nik.resourceworld.modules.ListenerModule;
6 | import org.bukkit.Bukkit;
7 | import org.bukkit.entity.Player;
8 | import org.bukkit.event.EventHandler;
9 | import org.bukkit.event.EventPriority;
10 | import org.bukkit.event.player.PlayerQuitEvent;
11 |
12 | public class LeaveWorld extends ListenerModule {
13 |
14 | public LeaveWorld(ResourceWorld plugin) {
15 | super(Config.Setting.SETTINGS_TELEPORT_TO_SPAWN.getBoolean(), plugin);
16 | }
17 |
18 | @EventHandler(priority = EventPriority.LOWEST)
19 | public void onLeave(PlayerQuitEvent e) {
20 |
21 | Player player = e.getPlayer();
22 |
23 | if (this.plugin.getResourceWorlds()
24 | .values()
25 | .stream()
26 | .anyMatch(rw -> rw.getName().equals(player.getWorld().getName()))) {
27 | player.teleport(Bukkit.getWorld(Config.Setting.SETTINGS_SPAWN_WORLD.getString()).getSpawnLocation());
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/modules/impl/Portals.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.modules.impl;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.files.Config;
5 | import me.nik.resourceworld.modules.ListenerModule;
6 | import org.bukkit.Bukkit;
7 | import org.bukkit.Location;
8 | import org.bukkit.World;
9 | import org.bukkit.event.EventHandler;
10 | import org.bukkit.event.EventPriority;
11 | import org.bukkit.event.player.PlayerPortalEvent;
12 |
13 | public class Portals extends ListenerModule {
14 |
15 | public Portals(ResourceWorld plugin) {
16 | super(Config.Setting.NETHER_PORTALS_ENABLED.getBoolean() || Config.Setting.END_PORTALS_ENABLED.getBoolean(), plugin);
17 | }
18 |
19 | private void handleEndPortal(PlayerPortalEvent e) {
20 | //Overworld -> End
21 | if (e.getFrom().getWorld().getEnvironment() == World.Environment.NORMAL) {
22 |
23 | if (!Config.Setting.END_PORTALS_ONLY_RESOURCE.getBoolean() && e.getFrom().getWorld().getName().equals(Config.Setting.WORLD_NAME.getString())) {
24 |
25 | World world = Bukkit.getWorld(Config.Setting.END_NAME.getString());
26 |
27 | if (world == null) return;
28 |
29 | Location to = e.getTo();
30 |
31 | try {
32 |
33 | e.setTo(new Location(world, to.getX(), to.getY(), to.getZ()));
34 |
35 | } catch (NullPointerException ignored) {
36 |
37 | /*
38 | I don't know why i did this, this is from two years ago.
39 | I'm guessing there's a good reason for it?
40 | */
41 | Location loc = world.getHighestBlockAt(world.getSpawnLocation()).getLocation();
42 |
43 | e.setTo(new Location(world, loc.getX(), loc.getY(), loc.getZ()));
44 | }
45 | }
46 | //End -> Overworld
47 | } else if (e.getFrom().getWorld().getName().equals(Config.Setting.END_NAME.getString())) {
48 |
49 | Location from = e.getFrom();
50 |
51 | e.setTo(new Location(Bukkit.getWorld(Config.Setting.END_PORTALS_PORTALWORLD.getString()), from.getX(), from.getY(), from.getZ()));
52 | }
53 | }
54 |
55 | private void handleNetherPortal(PlayerPortalEvent e) {
56 | //Overworld -> Nether
57 | if (e.getFrom().getWorld().getEnvironment() == World.Environment.NORMAL) {
58 |
59 | if (Config.Setting.NETHER_PORTALS_ONLY_RESOURCE.getBoolean() && !e.getFrom().getWorld().getName().equals(Config.Setting.WORLD_NAME.getString()))
60 | return;
61 |
62 | World world = Bukkit.getWorld(Config.Setting.NETHER_NAME.getString());
63 |
64 | if (world == null) return;
65 |
66 | Location from = e.getFrom();
67 |
68 | double x, y, z;
69 |
70 | if (Config.Setting.NETHER_PORTALS_VANILLA_RATIO.getBoolean()) {
71 |
72 | x = from.getX() / 8;
73 | y = from.getY() / 8;
74 | z = from.getZ() / 8;
75 |
76 | } else {
77 |
78 | x = from.getX();
79 | y = from.getY();
80 | z = from.getZ();
81 | }
82 |
83 | e.setTo(new Location(world, x, y, z));
84 |
85 | //End -> Overworld
86 | } else if (e.getFrom().getWorld().getName().equals(Config.Setting.NETHER_NAME.getString())) {
87 |
88 | Location from = e.getFrom();
89 |
90 | e.setTo(new Location(Bukkit.getWorld(Config.Setting.NETHER_PORTALS_PORTALWORLD.getString()), from.getX(), from.getY(), from.getZ()));
91 | }
92 | }
93 |
94 | @EventHandler(priority = EventPriority.MONITOR)
95 | public void onPortalEnd(PlayerPortalEvent e) {
96 | switch (e.getCause()) {
97 | case NETHER_PORTAL:
98 | handleNetherPortal(e);
99 | break;
100 | case END_PORTAL:
101 | handleEndPortal(e);
102 | break;
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/modules/impl/Suffocation.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.modules.impl;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.files.Config;
5 | import me.nik.resourceworld.modules.ListenerModule;
6 | import org.bukkit.entity.Player;
7 | import org.bukkit.event.EventHandler;
8 | import org.bukkit.event.entity.EntityDamageEvent;
9 |
10 | public class Suffocation extends ListenerModule {
11 |
12 | public Suffocation(ResourceWorld plugin) {
13 | super((Config.Setting.WORLD_DISABLE_SUFFOCATION.getBoolean()
14 | || Config.Setting.NETHER_DISABLE_SUFFOCATION.getBoolean()
15 | || Config.Setting.END_DISABLE_SUFFOCATION.getBoolean()), plugin);
16 | }
17 |
18 | @EventHandler
19 | public void onDamage(EntityDamageEvent e) {
20 | if (!(e.getEntity() instanceof Player) || !(e.getCause() == EntityDamageEvent.DamageCause.SUFFOCATION)) return;
21 |
22 | String world = e.getEntity().getWorld().getName();
23 |
24 | if (world.equals(Config.Setting.WORLD_NAME.getString())) {
25 | e.setCancelled(Config.Setting.WORLD_DISABLE_SUFFOCATION.getBoolean());
26 | } else if (world.equals(Config.Setting.NETHER_NAME.getString())) {
27 | e.setCancelled(Config.Setting.NETHER_DISABLE_SUFFOCATION.getBoolean());
28 | } else if (world.equals(Config.Setting.END_NAME.getString())) {
29 | e.setCancelled(Config.Setting.END_DISABLE_SUFFOCATION.getBoolean());
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/tasks/AlwaysDay.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.tasks;
2 |
3 | import me.nik.resourceworld.files.Config;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.scheduler.BukkitRunnable;
6 |
7 | public class AlwaysDay extends BukkitRunnable {
8 |
9 | @Override
10 | public void run() {
11 | Bukkit.getWorld(Config.Setting.WORLD_NAME.getString()).setTime(1000L);
12 | }
13 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/tasks/ResetEndWorld.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.tasks;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.api.ResourceWorldType;
5 | import org.bukkit.scheduler.BukkitRunnable;
6 |
7 | public class ResetEndWorld extends BukkitRunnable {
8 |
9 | private final ResourceWorld plugin;
10 |
11 | public ResetEndWorld(ResourceWorld plugin) {
12 | this.plugin = plugin;
13 | }
14 |
15 | @Override
16 | public void run() {
17 | this.plugin.getResourceWorld(ResourceWorldType.RESOURCE_END).reset();
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/tasks/ResetNetherWorld.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.tasks;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.api.ResourceWorldType;
5 | import org.bukkit.scheduler.BukkitRunnable;
6 |
7 | public class ResetNetherWorld extends BukkitRunnable {
8 |
9 | private final ResourceWorld plugin;
10 |
11 | public ResetNetherWorld(ResourceWorld plugin) {
12 | this.plugin = plugin;
13 | }
14 |
15 | @Override
16 | public void run() {
17 | this.plugin.getResourceWorld(ResourceWorldType.RESOURCE_NETHER).reset();
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/tasks/ResetWorld.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.tasks;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.api.ResourceWorldType;
5 | import org.bukkit.scheduler.BukkitRunnable;
6 |
7 | public class ResetWorld extends BukkitRunnable {
8 |
9 | private final ResourceWorld plugin;
10 |
11 | public ResetWorld(ResourceWorld plugin) {
12 | this.plugin = plugin;
13 | }
14 |
15 | @Override
16 | public void run() {
17 | this.plugin.getResourceWorld(ResourceWorldType.RESOURCE_WORLD).reset();
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/utils/ChatUtils.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.utils;
2 |
3 | import me.nik.resourceworld.managers.custom.ResourceWorldException;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.ChatColor;
6 |
7 | public class ChatUtils {
8 |
9 | private ChatUtils() {
10 | throw new ResourceWorldException("This is a static class dummy!");
11 | }
12 |
13 | /**
14 | * @param msg The message to format
15 | * @return The formatted message
16 | */
17 | public static String format(String msg) {
18 | return ChatColor.translateAlternateColorCodes('&', msg);
19 | }
20 |
21 | /**
22 | * @param message The message to send to the console
23 | */
24 | public static void consoleMessage(String message) {
25 | Bukkit.getServer().getConsoleSender().sendMessage(message);
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/utils/LocationFinder.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.utils;
2 |
3 | import io.papermc.lib.PaperLib;
4 | import me.nik.resourceworld.files.Config;
5 | import org.bukkit.Chunk;
6 | import org.bukkit.Location;
7 | import org.bukkit.Sound;
8 | import org.bukkit.World;
9 | import org.bukkit.block.Block;
10 | import org.bukkit.block.BlockFace;
11 | import org.bukkit.entity.Player;
12 | import org.bukkit.potion.PotionEffect;
13 | import org.bukkit.potion.PotionEffectType;
14 |
15 | import java.util.Random;
16 | import java.util.concurrent.CompletableFuture;
17 |
18 | public class LocationFinder {
19 |
20 | private static final Random random = new Random();
21 |
22 | public void teleportSafely(Player player, World world) {
23 |
24 | final World.Environment environment = world.getEnvironment();
25 |
26 | int x, z;
27 | final boolean nether;
28 |
29 | switch (environment) {
30 |
31 | case NETHER:
32 |
33 | x = randomInt(Config.Setting.TELEPORT_NETHER_MAX_RANGE.getInt());
34 | z = randomInt(Config.Setting.TELEPORT_NETHER_MAX_RANGE.getInt());
35 | nether = true;
36 |
37 | break;
38 |
39 | case THE_END:
40 |
41 | x = randomInt(Config.Setting.TELEPORT_END_MAX_RANGE.getInt());
42 | z = randomInt(Config.Setting.TELEPORT_END_MAX_RANGE.getInt());
43 | nether = false;
44 |
45 | break;
46 |
47 | default:
48 |
49 | x = randomInt(Config.Setting.TELEPORT_WORLD_MAX_RANGE.getInt());
50 | z = randomInt(Config.Setting.TELEPORT_WORLD_MAX_RANGE.getInt());
51 | nether = false;
52 |
53 | break;
54 | }
55 |
56 | Location location = new Location(world, x, (world.getHighestBlockYAt(x, z) + 1), z);
57 |
58 | //Load the chunk.
59 | CompletableFuture chunk = PaperLib.getChunkAtAsync(location);
60 |
61 | //Once it's grabbed, execute the following action.
62 | chunk.thenRunAsync(() -> {
63 |
64 | //Special things we need to account for the nether world.
65 | if (nether) {
66 |
67 | //Usually the best height.
68 | location.setY(80);
69 |
70 | //Keep subtracting until we reach the ground.
71 | while (world.getBlockAt(location).isEmpty()) {
72 | location.subtract(0, 1, 0);
73 | }
74 |
75 | //Add one to make sure the player teleports on top of the block.
76 | location.add(0, 1, 0);
77 | }
78 |
79 | //If the location is safe, proceed otherwise just look for another location.
80 | if (isLocationSafe(location, world, environment)) {
81 |
82 | //Finally teleport and apply effects on the main thread.
83 | TaskUtils.task(() -> {
84 |
85 | PaperLib.teleportAsync(player, location);
86 |
87 | //Idiot proof
88 | try {
89 |
90 | if (Config.Setting.TELEPORT_EFFECTS_ENABLED.getBoolean()) {
91 | player.addPotionEffect(
92 | new PotionEffect(
93 | PotionEffectType.getByName(Config.Setting.TELEPORT_EFFECT.getString()),
94 | Config.Setting.TELEPORT_EFFECT_DURATION.getInt() * 20,
95 | Config.Setting.TELEPORT_EFFECT_AMPLIFIER.getInt()));
96 | }
97 |
98 | if (Config.Setting.TELEPORT_SOUND_ENABLED.getBoolean()) {
99 | player.playSound(player.getLocation(), Sound.valueOf(Config.Setting.TELEPORT_SOUND.getString()), 2, 2);
100 | }
101 |
102 | } catch (IllegalArgumentException ignored) {
103 | }
104 | });
105 |
106 | } else teleportSafely(player, world); //Repeat
107 | });
108 | }
109 |
110 | private boolean isLocationSafe(Location location, World world, World.Environment environment) {
111 |
112 | int blockX = location.getBlockX();
113 | int blockY = location.getBlockY();
114 | int blockZ = location.getBlockZ();
115 |
116 | final Block feet = world.getBlockAt(blockX, blockY, blockZ);
117 |
118 | if (!feet.getRelative(BlockFace.UP).isEmpty()) return false;
119 |
120 | switch (environment) {
121 |
122 | case NETHER:
123 |
124 | for (int x = (blockX - 1); x <= (blockX + 1); x++) {
125 | for (int y = (blockY - 1); y <= (blockY + 1); y++) {
126 | for (int z = (blockZ - 1); z <= (blockZ + 1); z++) {
127 | //Make sure no liquid (Lava) is nearby.
128 | if (world.getBlockAt(x, y, z).isLiquid()) return false;
129 | }
130 | }
131 | }
132 |
133 | return true;
134 |
135 | case THE_END:
136 | //Make sure the player is not floating
137 | return !feet.getRelative(BlockFace.DOWN, 2).isEmpty();
138 | }
139 |
140 | //Return false on liquid otherwise the player will only teleport in the sea.
141 | return !feet.getRelative(BlockFace.DOWN).isLiquid();
142 | }
143 |
144 | private int randomInt(int value) {
145 |
146 | int min = -value;
147 |
148 | return random.nextInt((value - min) + 1) + min;
149 | }
150 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/utils/MiscUtils.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.utils;
2 |
3 | import me.nik.resourceworld.files.Config;
4 | import me.nik.resourceworld.managers.custom.ResourceWorldException;
5 | import org.bukkit.Bukkit;
6 | import org.bukkit.Location;
7 | import org.bukkit.World;
8 |
9 | import java.io.File;
10 | import java.util.concurrent.TimeUnit;
11 |
12 | public class MiscUtils {
13 |
14 | private static final boolean LEGACY = Bukkit.getVersion().contains("1.8")
15 | || Bukkit.getVersion().contains("1.9")
16 | || Bukkit.getVersion().contains("1.10")
17 | || Bukkit.getVersion().contains("1.11")
18 | || Bukkit.getVersion().contains("1.12");
19 |
20 | private MiscUtils() {
21 | throw new ResourceWorldException("This is a static class dummy!");
22 | }
23 |
24 | public static void deleteDirectory(File directory) {
25 | if (directory.exists()) {
26 | File[] files = directory.listFiles();
27 | if (files != null)
28 | for (File file : files) {
29 | if (file.isDirectory()) {
30 | deleteDirectory(file);
31 | } else {
32 | file.delete();
33 | }
34 | }
35 | }
36 | }
37 |
38 | /**
39 | * Convert a millisecond duration to a string format
40 | *
41 | * @param millis A duration to convert to a string form
42 | * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
43 | */
44 | public static String getDurationBreakdown(long millis) {
45 |
46 | final long days = TimeUnit.MILLISECONDS.toDays(millis);
47 | millis -= TimeUnit.DAYS.toMillis(days);
48 |
49 | final long hours = TimeUnit.MILLISECONDS.toHours(millis);
50 | millis -= TimeUnit.HOURS.toMillis(hours);
51 |
52 | final long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
53 | millis -= TimeUnit.MINUTES.toMillis(minutes);
54 |
55 | final long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
56 |
57 | String format = Config.Setting.SETTINGS_RESET_FORMAT.getString();
58 |
59 | if (days > 0) {
60 |
61 | format = format.replace("%days%", String.valueOf(days));
62 |
63 | } else {
64 |
65 | format = format.replace("%days%", String.valueOf(0));
66 | }
67 |
68 | if (hours > 0) {
69 |
70 | format = format.replace("%hours%", String.valueOf(hours));
71 |
72 | } else {
73 |
74 | format = format.replace("%hours%", String.valueOf(0));
75 | }
76 |
77 | if (minutes > 0) {
78 |
79 | format = format.replace("%minutes%", String.valueOf(minutes));
80 |
81 | } else {
82 |
83 | format = format.replace("%minutes%", String.valueOf(0));
84 | }
85 |
86 | if (seconds > 0) {
87 |
88 | format = format.replace("%seconds%", String.valueOf(seconds));
89 |
90 | } else {
91 |
92 | format = format.replace("%seconds%", String.valueOf(0));
93 | }
94 |
95 | return ChatUtils.format(format);
96 | }
97 |
98 | /**
99 | * Convert a location to a string seperated by a comma
100 | * So you can later grab it and convert it to a location by splitting the comma
101 | *
102 | * @param location The location
103 | * @return The location as a string
104 | */
105 | public static String locationToString(final Location location) {
106 | return location.getX() + "," +
107 | location.getY() + "," +
108 | location.getZ() + "," +
109 | location.getWorld().getName();
110 | }
111 |
112 | /**
113 | * Convert a string to a location
114 | *
115 | * @param location The location as a string
116 | * @return The bukkit location
117 | */
118 | public static Location stringToLocation(final String location) {
119 | final String[] data = location.split(",");
120 |
121 | try {
122 | final double x = Double.parseDouble(data[0]);
123 | final double y = Double.parseDouble(data[1]);
124 | final double z = Double.parseDouble(data[2]);
125 | final World world = Bukkit.getWorld(data[3]);
126 |
127 | return new Location(world, x, y, z);
128 | } catch (NumberFormatException | NullPointerException e) {
129 | e.printStackTrace();
130 | }
131 |
132 | return null;
133 | }
134 |
135 | public static boolean isLegacy() {
136 | return LEGACY;
137 | }
138 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/utils/TaskUtils.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.utils;
2 |
3 | import me.nik.resourceworld.ResourceWorld;
4 | import me.nik.resourceworld.managers.custom.ResourceWorldException;
5 | import org.bukkit.Bukkit;
6 | import org.bukkit.scheduler.BukkitTask;
7 |
8 | public final class TaskUtils {
9 |
10 | private TaskUtils() {
11 | throw new ResourceWorldException("This is a static class dummy!");
12 | }
13 |
14 | public static BukkitTask task(Runnable runnable) {
15 | return Bukkit.getScheduler().runTask(ResourceWorld.getInstance(), runnable);
16 | }
17 |
18 | public static BukkitTask taskLater(Runnable runnable, long delay) {
19 | return Bukkit.getScheduler().runTaskLater(ResourceWorld.getInstance(), runnable, delay);
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/utils/custom/ExpiringMap.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.utils.custom;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class ExpiringMap extends HashMap {
7 |
8 | private final long expireMillis;
9 |
10 | private final Map> map = new HashMap<>();
11 |
12 | public ExpiringMap(long expireMillis) {
13 | this.expireMillis = expireMillis;
14 | }
15 |
16 | @Override
17 | public V get(Object key) {
18 |
19 | validate();
20 |
21 | for (Pair pair : this.map.values()) {
22 |
23 | if (pair.getKey() == key) return pair.getValue();
24 | }
25 |
26 | return null;
27 | }
28 |
29 | public V removeOrDefault(Object key, V defaultValue) {
30 |
31 | validate();
32 |
33 | Pair pair = null;
34 |
35 | for (Pair kvPair : this.map.values()) {
36 |
37 | if (kvPair.getKey() != key) continue;
38 |
39 | pair = kvPair;
40 | }
41 |
42 | if (pair != null) {
43 |
44 | this.map.values().remove(pair);
45 |
46 | return pair.getValue();
47 | }
48 |
49 | return defaultValue;
50 | }
51 |
52 | @Override
53 | public V getOrDefault(Object key, V defaultValue) {
54 |
55 | validate();
56 |
57 | V v = null;
58 |
59 | for (Pair pair : this.map.values()) {
60 |
61 | if (pair.getKey() != key) continue;
62 |
63 | v = pair.getValue();
64 | }
65 |
66 | return v != null ? v : defaultValue;
67 | }
68 |
69 | @Override
70 | public V put(K key, V value) {
71 |
72 | validate();
73 |
74 | this.map.put(System.currentTimeMillis(), new Pair<>(key, value));
75 |
76 | return value;
77 | }
78 |
79 | @Override
80 | public V putIfAbsent(K key, V value) {
81 |
82 | validate();
83 |
84 | V v = null;
85 |
86 | for (Pair pair : this.map.values()) {
87 |
88 | if (pair.getKey() != key) continue;
89 |
90 | v = pair.getValue();
91 | }
92 |
93 | if (v == null) v = this.put(key, value);
94 |
95 | return v;
96 | }
97 |
98 | @Override
99 | public int size() {
100 |
101 | validate();
102 |
103 | return this.map.size();
104 | }
105 |
106 | @Override
107 | public boolean containsKey(Object key) {
108 |
109 | validate();
110 |
111 | for (Pair pair : this.map.values()) {
112 |
113 | if (pair.getKey() == key) return true;
114 | }
115 |
116 | return false;
117 | }
118 |
119 | @Override
120 | public boolean containsValue(Object value) {
121 |
122 | validate();
123 |
124 | for (Pair pair : this.map.values()) {
125 |
126 | if (pair.getValue() == value) return true;
127 | }
128 |
129 | return false;
130 | }
131 |
132 | @Override
133 | public void clear() {
134 | this.map.clear();
135 | }
136 |
137 | private void validate() {
138 | this.map.keySet().removeIf(timeStamp -> System.currentTimeMillis() - timeStamp > this.expireMillis);
139 | }
140 | }
--------------------------------------------------------------------------------
/src/main/java/me/nik/resourceworld/utils/custom/Pair.java:
--------------------------------------------------------------------------------
1 | package me.nik.resourceworld.utils.custom;
2 |
3 | public class Pair {
4 |
5 | private T key;
6 | private Y value;
7 |
8 | public Pair(T key, Y value) {
9 | this.key = key;
10 | this.value = value;
11 | }
12 |
13 | public Pair(Pair pair) {
14 | this.key = pair.key;
15 | this.value = pair.value;
16 | }
17 |
18 | public T getKey() {
19 | return key;
20 | }
21 |
22 | public void setKey(T key) {
23 | this.key = key;
24 | }
25 |
26 | public Y getValue() {
27 | return value;
28 | }
29 |
30 | public void setValue(Y value) {
31 | this.value = value;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return "Pair{" +
37 | "key=" + key +
38 | ", value=" + value +
39 | '}';
40 | }
41 | }
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: ResourceWorld
2 | version: ${project.version}
3 | main: me.nik.resourceworld.ResourceWorld
4 | api-version: 1.13
5 | authors: [ Nik ]
6 | description: ${project.description}
7 | website: https://discord.gg/m7j2Y9H
8 | softdepend: [ PlaceholderAPI, Vault ]
9 | commands:
10 | resource:
11 | description: Unlimited resources!
12 | aliases: [ resourceworld, rw ]
13 | permissions:
14 | rw.tp:
15 | description: Randomly Teleport To The Resource World!
16 | default: true
17 | rw.tp.nether:
18 | description: Randomly Teleport To The Nether Resource World!
19 | rw.tp.end:
20 | description: Randomly Teleport To The End Resource World!
21 | rw.tp.*:
22 | description: Access To Teleport To All The Resource Worlds!
23 | default: op
24 | children:
25 | rw.tp: true
26 | rw.tp.nether: true
27 | rw.tp.end: true
28 | rw.admin:
29 | description: Access to the Resource World admin commands!
30 | default: op
--------------------------------------------------------------------------------
/version.txt:
--------------------------------------------------------------------------------
1 | 2.1.0
--------------------------------------------------------------------------------