parent
6c1e0da6b6
commit
d54508cc81
15 changed files with 156 additions and 41 deletions
46
README.md
46
README.md
|
@ -1,19 +1,39 @@
|
||||||
# tweaks724
|
# tweaks724
|
||||||
|
|
||||||
Dependencies: ProtocolLib
|
Stuff no<sub><sup>t many</sup></sub> other plugins have.
|
||||||
|
|
||||||
### Caveats
|
Dependencies:
|
||||||
Disable "secure chat"
|
- [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) (optional, but you lose a lot)
|
||||||
|
|
||||||
### Chatrooms
|
# Features
|
||||||
- `/c` to see info about current chatroom
|
|
||||||
- `/c <name>` to join a chatroom
|
|
||||||
- `/cm create <name>` to create a chatroom
|
|
||||||
- `/cm set* <name>` to change a setting (for owners)
|
|
||||||
|
|
||||||
### Commands
|
Those with <sup>P</sup> need ProtocolLib
|
||||||
- `/dkick` - discreet kick. The player will be kicked with a cryptic error message, and those smarter will think it's a plugin bug.[^1] Brilliant!
|
|
||||||
- `/ping` - checks ping. Ping is checked using a more accurate[^2] method
|
|
||||||
|
|
||||||
[^1]: or, better, client bug, if they don't trust their client
|
### World border <sup><sup><sub>P</sub></sup></sup>
|
||||||
[^2]: not
|
Hides the world border. It's still there, just invisible.
|
||||||
|
|
||||||
|
### Server brand <sup><sup><sub>P</sub></sup></sup>
|
||||||
|
Modify the F3 brand, optionally include player's ping and server performance
|
||||||
|
|
||||||
|
### Doors
|
||||||
|
Open two doors with one click. Knock on doors.
|
||||||
|
|
||||||
|
### MOTD <sup><sup><sub>P</sub></sup></sup>
|
||||||
|
Random MOTD for every ping
|
||||||
|
|
||||||
|
### Chat rooms
|
||||||
|
Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room.
|
||||||
|
|
||||||
|
### Compass
|
||||||
|
Holding a compass shows a bar with 4 directions and stuff like beds, lodestones, death pos (TODO) etc.
|
||||||
|
|
||||||
|
### Pomodoro
|
||||||
|
Self-discipline with a pomodoro timer that's actually forced
|
||||||
|
|
||||||
|
### Updater
|
||||||
|
Updates ALL[^1] your plugins
|
||||||
|
|
||||||
|
[^1]: Those on SpigotMC and that release updates there
|
||||||
|
|
||||||
|
### Hardcore <sup><sup><sub>P</sub></sup></sup>
|
||||||
|
Hardcore hearts by chance
|
||||||
|
|
26
src/main/java/eu/m724/tweaks/Language.java
Normal file
26
src/main/java/eu/m724/tweaks/Language.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Minecon724
|
||||||
|
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||||
|
* in the project root for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.m724.tweaks;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class Language {
|
||||||
|
private final ResourceBundle resourceBundle;
|
||||||
|
|
||||||
|
private static Language INSTANCE = null;
|
||||||
|
|
||||||
|
Language(Locale locale) {
|
||||||
|
this.resourceBundle = ResourceBundle.getBundle("strings", locale);
|
||||||
|
|
||||||
|
INSTANCE = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(String key) {
|
||||||
|
return INSTANCE.resourceBundle.getString(key);
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ public record TweaksConfig(
|
||||||
|
|
||||||
boolean isProtocolLib = plugin.getServer().getPluginManager().getPlugin("ProtocolLib") != null;
|
boolean isProtocolLib = plugin.getServer().getPluginManager().getPlugin("ProtocolLib") != null;
|
||||||
|
|
||||||
int configVersion = config.getInt("magic number dont modify this", 0);
|
int configVersion = config.getInt("magic number don't modify this", 0);
|
||||||
RuntimeException exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION));
|
RuntimeException exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION));
|
||||||
if (configVersion == 0) {
|
if (configVersion == 0) {
|
||||||
throw exception;
|
throw exception;
|
||||||
|
|
|
@ -21,12 +21,16 @@ import eu.m724.tweaks.worldborder.WorldBorderManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class TweaksPlugin extends JavaPlugin {
|
public class TweaksPlugin extends JavaPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
long start = System.nanoTime();
|
||||||
|
|
||||||
TweaksConfig config = TweaksConfig.load(this);
|
TweaksConfig config = TweaksConfig.load(this);
|
||||||
|
new Language(Locale.US); // TODO
|
||||||
|
|
||||||
if (config.chatEnabled()) {
|
if (config.chatEnabled()) {
|
||||||
ChatManager chatManager = new ChatManager(this);
|
ChatManager chatManager = new ChatManager(this);
|
||||||
|
@ -81,6 +85,11 @@ public class TweaksPlugin extends JavaPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new HardcoreManager().init(this);
|
if (config.hardcoreEnabled()) {
|
||||||
|
new HardcoreManager().init(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getLogger().info("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class CompassListener implements Listener {
|
||||||
if (player.getBedSpawnLocation() != null) {
|
if (player.getBedSpawnLocation() != null) {
|
||||||
if (player.getBedSpawnLocation().getWorld().equals(player.getWorld())) {
|
if (player.getBedSpawnLocation().getWorld().equals(player.getWorld())) {
|
||||||
double respawnYaw = calculateYaw(player.getLocation(), player.getBedSpawnLocation());
|
double respawnYaw = calculateYaw(player.getLocation(), player.getBedSpawnLocation());
|
||||||
System.out.println(respawnYaw);
|
//System.out.println(respawnYaw);
|
||||||
currentPoints.put((int) respawnYaw, ChatColor.GREEN + "r");
|
currentPoints.put((int) respawnYaw, ChatColor.GREEN + "r");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
src/main/java/eu/m724/tweaks/full/FullListener.java
Normal file
20
src/main/java/eu/m724/tweaks/full/FullListener.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Minecon724
|
||||||
|
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||||
|
* in the project root for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.m724.tweaks.full;
|
||||||
|
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
|
||||||
|
public class FullListener implements Listener {
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent event) {
|
||||||
|
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && event.getPlayer().hasPermission("tweaks724.full.exempt")) {
|
||||||
|
event.allow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,9 +42,12 @@ public class MotdManager {
|
||||||
String motdSetName = TweaksConfig.getConfig().motdSet();
|
String motdSetName = TweaksConfig.getConfig().motdSet();
|
||||||
File motdSetsFile = new File(plugin.getDataFolder() + "/motd sets/" + motdSetName + ".txt");
|
File motdSetsFile = new File(plugin.getDataFolder() + "/motd sets/" + motdSetName + ".txt");
|
||||||
|
|
||||||
// if the directory didn't exist create example motd sets
|
motdSetsFile.getParentFile().mkdirs();
|
||||||
if (motdSetsFile.getParentFile().mkdirs()) {
|
// if this is a builtin set
|
||||||
plugin.saveResource("motd sets/" + motdSetName + ".txt", true);
|
plugin.saveResource("motd sets/" + motdSetName + ".txt", false);
|
||||||
|
|
||||||
|
if (!motdSetsFile.exists()) {
|
||||||
|
throw new RuntimeException("MOTD set \"%s\" doesn't exist (%s)".formatted(motdSetName, motdSetsFile.getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String fileContent = Files.readString(motdSetsFile.toPath());
|
String fileContent = Files.readString(motdSetsFile.toPath());
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class PluginScanner {
|
||||||
Set<SpigotResource> spigotResources = new HashSet<>();
|
Set<SpigotResource> spigotResources = new HashSet<>();
|
||||||
|
|
||||||
for (Plugin plugin : plugins) {
|
for (Plugin plugin : plugins) {
|
||||||
System.out.println("Found " + plugin.getName());
|
// System.out.println("Found " + plugin.getName());
|
||||||
String pluginName = plugin.getName();
|
String pluginName = plugin.getName();
|
||||||
|
|
||||||
if (!configuration.isSet(pluginName)) {
|
if (!configuration.isSet(pluginName)) {
|
||||||
|
@ -45,9 +45,9 @@ public class PluginScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
int pluginId = configuration.getInt(pluginName);
|
int pluginId = configuration.getInt(pluginName);
|
||||||
if (pluginId != -1) {
|
if (pluginId > 0) {
|
||||||
spigotResources.add(
|
spigotResources.add(
|
||||||
new SpigotResource(plugin, pluginId)
|
new SpigotResource(plugin, pluginId, pluginName)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
package eu.m724.tweaks.updater;
|
package eu.m724.tweaks.updater;
|
||||||
|
|
||||||
|
import eu.m724.tweaks.Language;
|
||||||
import eu.m724.tweaks.updater.cache.VersionedResource;
|
import eu.m724.tweaks.updater.cache.VersionedResource;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
@ -13,6 +14,8 @@ import org.bukkit.scheduler.BukkitRunnable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -23,6 +26,8 @@ public class UpdateChecker extends BukkitRunnable {
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final File cacheFile;
|
private final File cacheFile;
|
||||||
|
|
||||||
|
private final Set<VersionedResource> availableUpdates = new HashSet<>();
|
||||||
|
|
||||||
UpdateChecker(Plugin plugin, Set<VersionedResource> resources) {
|
UpdateChecker(Plugin plugin, Set<VersionedResource> resources) {
|
||||||
this.logger = Logger.getLogger(plugin.getLogger().getName() + "." + getClass().getSimpleName());
|
this.logger = Logger.getLogger(plugin.getLogger().getName() + "." + getClass().getSimpleName());
|
||||||
this.resources = resources; // TODO make a copy?
|
this.resources = resources; // TODO make a copy?
|
||||||
|
@ -30,9 +35,12 @@ public class UpdateChecker extends BukkitRunnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAll() {
|
private void checkAll() {
|
||||||
logger.info("Checking for updates");
|
//logger.info("Checking for updates");
|
||||||
|
availableUpdates.clear();
|
||||||
|
|
||||||
for (VersionedResource versionedResource : Set.copyOf(resources)) {
|
for (VersionedResource versionedResource : Set.copyOf(resources)) {
|
||||||
logger.info(versionedResource.resource().resourceId() + " " + versionedResource.resource().plugin().getName());
|
String pluginName = versionedResource.resource().plugin().getName();
|
||||||
|
//logger.info(versionedResource.resource().resourceId() + " " + versionedResource.resource().plugin().getName());
|
||||||
int page = versionedResource.running() != null ? versionedResource.running().page() : 1;
|
int page = versionedResource.running() != null ? versionedResource.running().page() : 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -40,29 +48,46 @@ public class UpdateChecker extends BukkitRunnable {
|
||||||
if (!versionedResource.equals(newResource)) {
|
if (!versionedResource.equals(newResource)) {
|
||||||
resources.remove(versionedResource);
|
resources.remove(versionedResource);
|
||||||
if (newResource.running() == null) {
|
if (newResource.running() == null) {
|
||||||
|
logger.info("Unable to find installed version of %s".formatted(pluginName));
|
||||||
if (versionedResource.running() != null) {
|
if (versionedResource.running() != null) {
|
||||||
logger.info("Did you downgrade %s? If so, clear cache");
|
logger.info("Did you downgrade %s? If so, clear cache".formatted(pluginName));
|
||||||
newResource = null;
|
}
|
||||||
|
} else {
|
||||||
|
if (!newResource.running().equals(newResource.latest())) {
|
||||||
|
availableUpdates.add(newResource);
|
||||||
|
//logger.info("Update available for %s. %d -> %d".formatted(pluginName, newResource.running().updateId(), newResource.latest().updateId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resources.remove(versionedResource);
|
|
||||||
resources.add(newResource);
|
resources.add(newResource);
|
||||||
// TODO notify and all
|
|
||||||
}
|
}
|
||||||
} catch (CompletionException e) {
|
} catch (CompletionException e) {
|
||||||
logger.severe("Unable to refresh %s: %s".formatted(versionedResource.resource().plugin().getName(), e.getMessage()));
|
logger.severe("Unable to refresh %s: %s".formatted(pluginName, e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void alert() {
|
||||||
|
int n = availableUpdates.size();
|
||||||
|
if (n == 0) return;
|
||||||
|
logger.info(Language.getString("updateAvailableNotice"));
|
||||||
|
|
||||||
|
availableUpdates.stream()
|
||||||
|
.map(u -> "- %s (%s -> %s)".formatted(u.resource().name(), u.running().label(), u.latest().label()))
|
||||||
|
.forEach(logger::info);
|
||||||
|
|
||||||
|
// TODO notify player
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
checkAll();
|
checkAll();
|
||||||
|
|
||||||
try (FileOutputStream outputStream = new FileOutputStream(cacheFile)) {
|
try (FileOutputStream outputStream = new FileOutputStream(cacheFile)) {
|
||||||
VersionCheckCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).collect(Collectors.toSet()));
|
VersionCheckCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).filter(Objects::nonNull).collect(Collectors.toSet()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alert();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class VersionCheckCache {
|
||||||
while (inputStream.available() > 0) {
|
while (inputStream.available() > 0) {
|
||||||
int read = inputStream.read(buffer);
|
int read = inputStream.read(buffer);
|
||||||
if (read < 8) break; // end of file
|
if (read < 8) break; // end of file
|
||||||
if (++i > 10000) throw new RuntimeException("File is too large");
|
if (++i > 10000) throw new RuntimeException("Cache file is too large");
|
||||||
|
|
||||||
ResourceVersion resourceVersion = getResourceVersion(buffer);
|
ResourceVersion resourceVersion = getResourceVersion(buffer);
|
||||||
versions.add(resourceVersion);
|
versions.add(resourceVersion);
|
||||||
|
@ -43,7 +43,7 @@ public class VersionCheckCache {
|
||||||
int page = ((bytes[3] & 0xFF) << 8) | (bytes[4] & 0xFF);
|
int page = ((bytes[3] & 0xFF) << 8) | (bytes[4] & 0xFF);
|
||||||
int versionId = ((bytes[5] & 0xFF) << 16) | ((bytes[6] & 0xFF) << 8) | (bytes[7] & 0xFF);
|
int versionId = ((bytes[5] & 0xFF) << 16) | ((bytes[6] & 0xFF) << 8) | (bytes[7] & 0xFF);
|
||||||
|
|
||||||
return new ResourceVersion(resourceId, page, versionId);
|
return new ResourceVersion(resourceId, page, versionId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeResourceVersion(ResourceVersion resourceVersion, OutputStream outputStream) throws IOException {
|
private static void writeResourceVersion(ResourceVersion resourceVersion, OutputStream outputStream) throws IOException {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class VersionFinder extends CompletableFuture<VersionedResource> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start() {
|
private void start() {
|
||||||
System.out.printf("STarting for %d %s\n", resource.resourceId(), resource.plugin().getName());
|
//System.out.printf("STarting for %d %s\n", resource.resourceId(), resource.plugin().getName());
|
||||||
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
|
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
|
@ -50,7 +50,7 @@ public class VersionFinder extends CompletableFuture<VersionedResource> {
|
||||||
|
|
||||||
int page;
|
int page;
|
||||||
for (page = fromPage; page < 1000; page++) {
|
for (page = fromPage; page < 1000; page++) {
|
||||||
System.out.println("Page " + page);
|
//System.out.println("Page " + page);
|
||||||
String url = "https://api.spigotmc.org/simple/0.2/index.php?action=getResourceUpdates&page=%d&id=%d".formatted(page, resource.resourceId());
|
String url = "https://api.spigotmc.org/simple/0.2/index.php?action=getResourceUpdates&page=%d&id=%d".formatted(page, resource.resourceId());
|
||||||
|
|
||||||
HttpRequest request;
|
HttpRequest request;
|
||||||
|
@ -78,22 +78,24 @@ public class VersionFinder extends CompletableFuture<VersionedResource> {
|
||||||
runningVersion = new ResourceVersion(
|
runningVersion = new ResourceVersion(
|
||||||
resource.resourceId(),
|
resource.resourceId(),
|
||||||
page,
|
page,
|
||||||
versionJson.get("id").getAsInt()
|
versionJson.get("id").getAsInt(),
|
||||||
|
versionJson.get("resource_version").getAsString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
latestVersion = new ResourceVersion(
|
latestVersion = new ResourceVersion(
|
||||||
resource.resourceId(),
|
resource.resourceId(),
|
||||||
page,
|
page,
|
||||||
versionJson.get("id").getAsInt()
|
versionJson.get("id").getAsInt(),
|
||||||
|
versionJson.get("resource_version").getAsString()
|
||||||
);
|
);
|
||||||
System.out.printf("%d %d %s\n", page, versionJson.get("id").getAsInt(), versionJson.get("resource_version").getAsString());
|
//System.out.printf("%d %d %s\n", page, versionJson.get("id").getAsInt(), versionJson.get("resource_version").getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonArray.size() < 10) break;
|
if (jsonArray.size() < 10) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
System.out.println("Done");
|
//System.out.println("Done");
|
||||||
|
|
||||||
if (page > 999) {
|
if (page > 999) {
|
||||||
throw new Exception("Too many pages");
|
throw new Exception("Too many pages");
|
||||||
|
|
|
@ -9,5 +9,6 @@ package eu.m724.tweaks.updater.cache;
|
||||||
public record ResourceVersion(
|
public record ResourceVersion(
|
||||||
int resourceId,
|
int resourceId,
|
||||||
int page,
|
int page,
|
||||||
int updateId
|
int updateId,
|
||||||
|
String label
|
||||||
) { }
|
) { }
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
public record SpigotResource(
|
public record SpigotResource(
|
||||||
Plugin plugin,
|
Plugin plugin,
|
||||||
int resourceId
|
int resourceId,
|
||||||
|
String name
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# Here go installed plugins and their SpigotMC resource IDs
|
# Here go installed plugins and their SpigotMC resource IDs
|
||||||
# To ignore a plugin, set it to -1
|
# To ignore a plugin, set it to a negative number, like -1
|
||||||
|
# Pro tip: Prefix an ID with a minus to disable it without losing the ID
|
||||||
|
|
||||||
|
|
7
src/main/resources/strings.properties
Normal file
7
src/main/resources/strings.properties
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Minecon724
|
||||||
|
# Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||||
|
# in the project root for the full license text.
|
||||||
|
#
|
||||||
|
|
||||||
|
updateAvailableNotice = Available updates (%d):
|
Loading…
Reference in a new issue