12 Commits
Author SHA1 Message Date
Nassim Jahnke 3fe95d7c36 1.7.3 Release 2024-05-17 16:25:04 +02:00
Nassim Jahnke 4283964e0b Small refactors 2023-10-01 21:56:15 +10:00
Nassim JahnkeandPhillip Glanz 23f9ca8350 Add Folia support
Co-authored-by: Phillip Glanz <p.glanz@madfix.me>
2023-04-03 12:24:20 +02:00
Nassim Jahnke 423a552e5b Update bstats 2023-01-01 17:56:50 +01:00
Nassim Jahnke b5dc9d45e0 Update dependencies 2023-01-01 17:53:12 +01:00
Nassim Jahnke 55a1857392 Bump version to 7.1.3-SNAPSHOT 2023-01-01 17:45:15 +01:00
Nassim Jahnke 24b97184cc 1.7.2 Release 2021-11-06 21:57:51 +01:00
Nassim Jahnke 8e10485e89 Add ability to set per-particle radius, speed, and offset 2021-11-06 21:53:12 +01:00
Nassim Jahnke 95a766d250 Update copyright header and name 2021-11-06 21:33:16 +01:00
KennyTV 75db35d027 Add sanity check when uncaching players 2020-04-23 18:38:05 +02:00
KennyTV b698132801 Replace domain redirection with proper discord link 2020-04-13 23:48:39 +02:00
KennyTV a7085b1bc0 1.7.1 Release
* Add max selection size option
* Limit the maximum advanced grid size to make them more beautiful
* Fix send to all particles not working (Fixes #7)
2020-04-12 13:59:25 +02:00
43 changed files with 528 additions and 498 deletions

No files matched your search

+2 -3
View File
@@ -1,6 +1,5 @@
# WorldEditSUI
[![Discord](https://img.shields.io/discord/489135856284729384.svg?label=Discord&logo=discord&logoColor=fff)](https://discord.gg/vGCUzHq)
[![Twitter](https://img.shields.io/twitter/follow/KennyTVN.svg?label=Twitter)](https://twitter.com/KennyTVN)
Sassy Minecraft plugin to show your current WorldEdit selection by displaying particles (which can be greatly customized in the plugin's config).
Compared to other server plugins with similar functionality, it aims at a higher performance and lesser memory impact by having a quite simplistic approach to calculating vectors.
@@ -9,10 +8,10 @@ You can read up on everything else and see examples on the [**Spigot page**](htt
## Legacy support
This branch supports Minecraft versions from 1.9 upwards.
If you want a jar that supports 1.8.4-1.8.9 as well, see the `1.8-support` branch / the [**last release to contain a 1.8 build**](https://github.com/KennyTV/WorldEditSUI/releases/tag/1.6.1).
If you want a jar that supports 1.8.4-1.8.9 as well, see the `1.8-support` branch / the [**last release to contain a 1.8 build**](https://github.com/kennytv/WorldEditSUI/releases/tag/1.6.1).
## Compiling
Use Maven to compile the project (`mvn clean package`).
Use Maven to compile the project (`mvn package`).
## Licence
This project is licensed under the [GNU General Public License](http://www.gnu.org/licenses/gpl-3.0).
+28 -8
View File
@@ -7,7 +7,7 @@
<groupId>eu.kennytv.worldeditsui</groupId>
<artifactId>worldedit-sui-parent</artifactId>
<packaging>pom</packaging>
<version>1.7</version>
<version>1.7.3</version>
<modules>
<module>worldedit-sui</module>
@@ -24,25 +24,25 @@
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>enginehub-repo</id>
<url>https://maven.sk89q.com/artifactory/repo/</url>
<url>https://maven.enginehub.org/repo/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.15.2-R0.1-SNAPSHOT</version>
<groupId>dev.folia</groupId>
<artifactId>folia-api</artifactId>
<version>1.20.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>19.0.0</version>
<version>24.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -53,7 +53,15 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<version>3.5.3</version>
<configuration>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>eu.kennytv.worldeditsui.lib.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
@@ -63,6 +71,18 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<archive>
<manifestEntries>
<paperweight-mappings-namespace>mojang</paperweight-mappings-namespace>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
<finalName>${project.name}-${project.version}</finalName>
<resources>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.worldeditsui</groupId>
<artifactId>worldedit-sui-parent</artifactId>
<version>1.7</version>
<version>1.7.3</version>
</parent>
<packaging>pom</packaging>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.worldeditsui</groupId>
<artifactId>we-compat</artifactId>
<version>1.7</version>
<version>1.7.3</version>
</parent>
<artifactId>we-compat-common</artifactId>
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@ public enum SelectionType {
NONE(null);
private static final Map<String, SelectionType> TYPES = new HashMap<>();
private final String key;
private final String key; // WE key, hence the inconsistent naming
SelectionType(final String key) {
this.key = key;
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.worldeditsui</groupId>
<artifactId>we-compat</artifactId>
<version>1.7</version>
<version>1.7.3</version>
</parent>
<artifactId>we6-compat</artifactId>
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,9 +41,15 @@ public final class ProtectedRegionHelper6 implements ProtectedRegionHelper {
@Override
public ProtectedRegionWrapper getRegion(final World world, final String regionName) {
final RegionManager regionManager = regionContainer.get(world);
if (regionManager == null) return null;
if (regionManager == null) {
return null;
}
final ProtectedRegion region = regionManager.getRegion(regionName);
if (region == null) {
return null;
}
final RegionType type = region.getType();
final com.sk89q.worldedit.world.World worldWrapper = new BukkitWorld(world);
switch (type) {
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,12 @@ import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.*;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.EllipsoidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.session.ClipboardHolder;
import eu.kennytv.worldeditsui.compat.RegionHelper;
import eu.kennytv.worldeditsui.compat.Simple2DVector;
+3 -3
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>eu.kennytv.worldeditsui</groupId>
<artifactId>we-compat</artifactId>
<version>1.7</version>
<version>1.7.3</version>
</parent>
<artifactId>we7-compat</artifactId>
@@ -21,13 +21,13 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.1.0-SNAPSHOT</version>
<version>7.2.13</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.2-SNAPSHOT</version>
<version>7.1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,9 +42,15 @@ public final class ProtectedRegionHelper7 implements ProtectedRegionHelper {
public ProtectedRegionWrapper getRegion(final World world, final String regionName) {
final BukkitWorld worldWrapper = new BukkitWorld(world);
final RegionManager regionManager = regionContainer.get(worldWrapper);
if (regionManager == null) return null;
if (regionManager == null) {
return null;
}
final ProtectedRegion region = regionManager.getRegion(regionName);
if (region == null) {
return null;
}
final RegionType type = region.getType();
switch (type) {
case CUBOID:
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,12 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector2;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.*;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.EllipsoidRegion;
import com.sk89q.worldedit.regions.Polygonal2DRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.session.ClipboardHolder;
import eu.kennytv.worldeditsui.compat.RegionHelper;
import eu.kennytv.worldeditsui.compat.Simple2DVector;
+17 -2
View File
@@ -6,11 +6,19 @@
<parent>
<groupId>eu.kennytv.worldeditsui</groupId>
<artifactId>worldedit-sui-parent</artifactId>
<version>1.7</version>
<version>1.7.3</version>
</parent>
<artifactId>worldedit-sui</artifactId>
<name>WorldEditSUI</name>
<url>https://github.com/kennytv/WorldEditSUI</url>
<developers>
<developer>
<id>kennytv</id>
<url>https://github.com/kennytv/</url>
</developer>
</developers>
<dependencies>
<dependency>
@@ -31,10 +39,17 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.1.0-SNAPSHOT</version>
<!--suppress VulnerableLibrariesLocal -->
<version>7.2.13</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -52,7 +52,9 @@ public final class Settings {
private int particleSendInterval;
private int particleViewDistance;
private long expiresAfterMillis;
private long maxSelectionSizeToDisplay;
private int maxPing;
private boolean useMaxSelectionSizeBypassPerm;
private boolean cacheLocations;
private boolean expiryEnabled;
private boolean expireMessage;
@@ -82,12 +84,25 @@ public final class Settings {
final YamlConfiguration config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), "config.yml"));
wandItem = config.getString("wand", "").toUpperCase().replace("MINECRAFT:", "");
particleViewDistance = config.getInt("particle-viewdistance", 99);
if (particleViewDistance < 1 || particleViewDistance > 500) {
plugin.getLogger().warning("To punish you for your deeds of setting the particle viewdistance to an astonishing "
+ particleViewDistance + ", it has been set to 2 blocks.");
plugin.getLogger().warning("Also, this puppy just died.\n"
+ " __\n" +
" (___()'`;\n" +
" /, /`\n" +
" \\\\\"--\\\\");
plugin.getLogger().warning("Is this what you wanted?");
particleViewDistance = 2;
}
particle = loadParticle(config, "particle", Particle.FLAME);
clipboardParticle = loadParticle(config, "clipboard-particle", Particle.VILLAGER_HAPPY);
wgRegionParticle = loadParticle(config, "wg-region-particle", Particle.VILLAGER_HAPPY);
maxPing = Math.max(config.getInt("max-ping"), 0);
try {
maxPing = Math.max(config.getInt("max-ping"), 0);
Player.Spigot.class.getDeclaredMethod("getPing");
} catch (final NoSuchMethodException ignored) {
if (maxPing != 0) {
@@ -145,19 +160,6 @@ public final class Settings {
showByDefault = config.getBoolean("show-selection-by-default", true);
showClipboardByDefault = config.getBoolean("show-clipboard-by-default");
particleViewDistance = config.getInt("particle-viewdistance", 99);
if (particleViewDistance < 1 || particleViewDistance > 500) {
plugin.getLogger().warning("To punish you for your deeds of setting the particle viewdistance to an astonishing "
+ particleViewDistance + ", it has been set to 2 blocks.");
plugin.getLogger().warning("Also, this puppy just died.\n"
+ " __\n" +
" (___()'`;\n" +
" /, /`\n" +
" \\\\\"--\\\\");
plugin.getLogger().warning("Is this what you wanted?");
particleViewDistance = 2;
}
expiryEnabled = config.getBoolean("particle-expiry.enabled", false);
if (expiryEnabled) {
expireMessage = config.getBoolean("particle-expiry.expire-message", true);
@@ -171,6 +173,9 @@ public final class Settings {
}
}
maxSelectionSizeToDisplay = Math.max(config.getLong("max-selection-size-to-display"), 0);
useMaxSelectionSizeBypassPerm = config.getBoolean("enable-max-selection-bypass-perm", true);
if (persistentToggles) {
final File file = new File(plugin.getDataFolder(), "userdata.yml");
if (!file.exists()) {
@@ -208,17 +213,29 @@ public final class Settings {
} catch (final Exception e) {
plugin.getLogger().warning("Unknown particle for " + s + ": " + particleName.toUpperCase());
plugin.getLogger().warning("Switched to default particle: " + defaultParticle);
return new ParticleData(defaultParticle, null);
return new ParticleData(defaultParticle, particleViewDistance);
}
double speed = 0;
double offX = 0;
double offY = 0;
double offZ = 0;
int radius = particleViewDistance;
final ConfigurationSection particleSection = section.getConfigurationSection(s + "-data");
if (particleSection != null) {
speed = Math.max(0, particleSection.getDouble("speed"));
offX = particleSection.getDouble("offX");
offY = particleSection.getDouble("offY");
offZ = particleSection.getDouble("offZ");
radius = Math.min(500, Math.max(1, particleSection.getInt("radius", radius))); // TODO warn if radius is too high
}
try {
final Object data = ParticleData.getExtraData(particle, section.getConfigurationSection(s + "-data"));
return new ParticleData(particle, data);
return new ParticleData(particle, radius, speed, offX, offY, offZ, ParticleData.getExtraData(particle, particleSection));
} catch (final Exception e) {
plugin.getLogger().warning("Error loading particle data of " + particleName + " - Missing data? You may read up on how to correctly set its data at the bottom of the plugin's Spigot page.");
plugin.getLogger().warning("Falling back to default particle: " + defaultParticle);
e.printStackTrace();
return new ParticleData(particle, null);
return new ParticleData(particle, particleViewDistance);
}
}
@@ -315,6 +332,14 @@ public final class Settings {
return maxPing;
}
public long getMaxSelectionSizeToDisplay() {
return maxSelectionSizeToDisplay;
}
public boolean useMaxSelectionSizeBypassPerm() {
return useMaxSelectionSizeBypassPerm;
}
public boolean isExpiryEnabled() {
return expiryEnabled;
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,29 +43,30 @@ import eu.kennytv.worldeditsui.drawer.base.DrawedType;
import eu.kennytv.worldeditsui.listener.PlayerJoinListener;
import eu.kennytv.worldeditsui.listener.PlayerQuitListener;
import eu.kennytv.worldeditsui.listener.WESelectionListener;
import eu.kennytv.worldeditsui.metrics.MetricsLite;
import eu.kennytv.worldeditsui.user.SelectionCache;
import eu.kennytv.worldeditsui.user.User;
import eu.kennytv.worldeditsui.user.UserManager;
import eu.kennytv.worldeditsui.util.Cancellable;
import eu.kennytv.worldeditsui.util.CancellableBukkitTask;
import eu.kennytv.worldeditsui.util.CancellableScheduledTask;
import eu.kennytv.worldeditsui.util.ParticleHelper;
import eu.kennytv.worldeditsui.util.Version;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.TimeUnit;
import org.bstats.bukkit.Metrics;
import org.bukkit.Location;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Nullable;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author KennyTV
*/
public final class WorldEditSUIPlugin extends JavaPlugin {
private static final boolean FOLIA = hasClass("io.papermc.paper.threadedregions.scheduler.EntityScheduler");
private static final String PREFIX = "§8[§eWorldEditSUI§8] ";
private RegionHelper regionHelper;
private ProtectedRegionHelper protectedRegionHelper;
@@ -76,8 +77,8 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
private WorldEditPlugin worldEditPlugin;
private Version version;
private Version newestVersion;
private int expiryTask = -1;
private int persistentTogglesTask = -1;
private Cancellable expiryTask;
private Cancellable persistentTogglesTask;
private boolean worldGuardEnabled;
@Override
@@ -93,6 +94,7 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
return;
}
boolean isWorldEdit7 = true;
try {
Class.forName("com.sk89q.worldedit.math.Vector2");
@@ -101,9 +103,10 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
}
regionHelper = isWorldEdit7 ? new RegionHelper7() : new RegionHelper6();
particleHelper = new ParticleHelper(settings);
settings = new Settings(this);
particleHelper = new ParticleHelper(settings);
userManager = new UserManager(settings);
drawManager = new DrawManager(this);
@@ -126,10 +129,10 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
command.setPermissionMessage(settings.getMessage("noPermission"));
// Start tasks
getServer().getScheduler().runTaskTimerAsynchronously(this, this::updateSelections, settings.getParticleSendInterval(), settings.getParticleSendInterval());
checkTasks();
runRepeatedAsync(this::updateSelections, settings.getParticleSendInterval(), settings.getParticleSendInterval());
reloadTasks();
new MetricsLite(this);
new Metrics(this, 5444);
}
@Override
@@ -140,16 +143,40 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
getServer().getOnlinePlayers().forEach(player -> userManager.deleteUser(player));
}
public Cancellable runRepeatedAsync(final Runnable runnable, final long delay, final long period) {
if (FOLIA) {
return new CancellableScheduledTask(getServer().getAsyncScheduler().runAtFixedRate(this, scheduledTask -> runnable.run(), delay * 50, period * 50, TimeUnit.MILLISECONDS));
} else {
return new CancellableBukkitTask(getServer().getScheduler().runTaskTimerAsynchronously(this, runnable, delay, period));
}
}
public Cancellable runRepeated(final Runnable runnable, final long delay, final long period) {
if (FOLIA) {
return new CancellableScheduledTask(getServer().getGlobalRegionScheduler().runAtFixedRate(this, task -> runnable.run(), delay, period));
} else {
return new CancellableBukkitTask(getServer().getScheduler().runTaskTimer(this, runnable, delay, period));
}
}
public void runAsync(final Runnable runnable) {
if (FOLIA) {
getServer().getAsyncScheduler().runNow(this, task -> runnable.run());
} else {
getServer().getScheduler().runTaskAsynchronously(this, runnable);
}
}
private void printEnableMessage() {
getLogger().info("Plugin by KennyTV");
getServer().getScheduler().runTaskAsynchronously(this, () -> {
updateAvailable();
getLogger().info("Plugin by kennytv");
runAsync(() -> {
checkForLatestVersion();
final int compare = version.compareTo(newestVersion);
if (compare == -1) {
if (compare < 0) {
getLogger().info("§cNewest version available: §aVersion " + newestVersion + "§c, you're on §a" + version);
} else if (compare == 1) {
} else if (compare > 0) {
if (version.getTag().equalsIgnoreCase("snapshot")) {
getLogger().info("§cYou're running a development version, please report bugs on the Discord server (https://kennytv.eu/discord).");
getLogger().info("§cYou're running a development version, please report bugs on the Discord server (https://discord.gg/vGCUzHq).");
} else {
getLogger().info("§cYou're running a version, that doesn't exist! §cN§ai§dc§ee§5!");
}
@@ -157,63 +184,77 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
});
}
public boolean updateAvailable() {
public boolean checkForLatestVersion() {
try {
final HttpURLConnection c = (HttpURLConnection) new URL("https://api.spigotmc.org/legacy/update.php?resource=60726").openConnection();
final String newVersionString = new BufferedReader(new InputStreamReader(c.getInputStream())).readLine().replaceAll("[a-zA-Z -]", "");
final Version newVersion = new Version(newVersionString);
if (newVersion.equals(version)) return false;
final URLConnection connection = new URL("https://hangar.papermc.io/api/v1/projects/WorldEditSUI/latestrelease").openConnection();
connection.setRequestProperty("User-Agent", "WorldEditSUI/" + getVersion());
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
final String newVersionString = reader.readLine();
final Version newVersion = new Version(newVersionString);
if (newVersion.equals(version)) {
return false;
}
newestVersion = newVersion;
return version.compareTo(newVersion) == -1;
newestVersion = newVersion;
return version.compareTo(newVersion) < 0;
}
} catch (final Exception ignored) {
return false;
}
}
public void checkTasks() {
public void reloadTasks() {
// Start tasks if not already running, or cancel them if one is running but now disabled in the config
if (expiryTask == -1 && settings.isExpiryEnabled()) {
expiryTask = getServer().getScheduler().runTaskTimer(this, () -> {
for (final User user : userManager.getUsers().values()) {
if (user.getExpireTimestamp() == 0) continue;
if (user.getExpireTimestamp() > System.currentTimeMillis()) continue;
if (expiryTask == null && settings.isExpiryEnabled()) {
expiryTask = runRepeated(this::expiryTask, 20, 20);
} else if (expiryTask != null && !settings.isExpiryEnabled()) {
expiryTask.cancel();
expiryTask = null;
user.setExpireTimestamp(0);
if (settings.hasExpireMessage()) {
getServer().getPlayer(user.getUuid()).sendMessage(settings.getMessage("idled"));
}
}
}, 20, 20).getTaskId();
} else if (expiryTask != -1 && !settings.isExpiryEnabled()) {
for (final User user : userManager.getUsers().values()) {
user.setExpireTimestamp(-1);
}
getServer().getScheduler().cancelTask(expiryTask);
expiryTask = -1;
}
if (persistentTogglesTask == -1 && settings.hasPersistentToggles()) {
if (persistentTogglesTask == null && settings.hasPersistentToggles()) {
// Check every 15 minutes
persistentTogglesTask = getServer().getScheduler().runTaskTimerAsynchronously(this, () -> settings.saveData(), 18000, 18000).getTaskId();
} else if (persistentTogglesTask != -1 && !settings.hasPersistentToggles()) {
getServer().getScheduler().cancelTask(persistentTogglesTask);
persistentTogglesTask = -1;
persistentTogglesTask = runRepeatedAsync(() -> settings.saveData(), 18000, 18000);
} else if (persistentTogglesTask != null && !settings.hasPersistentToggles()) {
persistentTogglesTask.cancel();
persistentTogglesTask = null;
}
}
private void expiryTask() {
for (final User user : userManager.getUsers().values()) {
if (user.getExpireTimestamp() == 0) continue;
if (user.getExpireTimestamp() > System.currentTimeMillis()) continue;
user.setExpireTimestamp(0);
if (settings.hasExpireMessage()) {
getServer().getPlayer(user.getUuid()).sendMessage(settings.getMessage("idled"));
}
}
}
private void updateSelections() {
for (final Player player : getServer().getOnlinePlayers()) {
if (!player.isOnline()) continue;
if (!player.isOnline()) {
continue;
}
final User user = userManager.getUser(player);
if (user == null) continue;
// Check for sending restrictions
if (!user.isSelectionShown() && !user.isClipboardShown()) continue;
if (settings.isExpiryEnabled() && user.getExpireTimestamp() == 0)
if (user == null) {
continue;
if (settings.getPermission() != null && !player.hasPermission(settings.getPermission())) continue;
if (settings.getMaxPing() != 0 && player.spigot().getPing() > settings.getMaxPing()) continue;
}
// Check for sending restrictions
if (!user.isSelectionShown() && !user.isClipboardShown()
|| settings.isExpiryEnabled() && user.getExpireTimestamp() == 0
|| settings.getPermission() != null && !player.hasPermission(settings.getPermission())
|| settings.getMaxPing() != 0 && player.spigot().getPing() > settings.getMaxPing()) {
continue;
}
final LocalSession session = worldEditPlugin.getSession(player);
final RegionSelector selector = session.getRegionSelector(new BukkitWorld(player.getWorld()));
@@ -226,42 +267,47 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
// Clipboard
if (user.isClipboardShown()) {
try {
final ClipboardHolder holder = session.getClipboard();
final Clipboard clipboard = holder.getClipboard();
final Location location = player.getLocation();
final SimpleVector origin = regionHelper.getOrigin(clipboard);
// Transform the clipboard if necessary
final Transform transform = holder.getTransform();
final Region region = transform.isIdentity() ? clipboard.getRegion() : regionHelper.transformAndReShift(holder, clipboard.getRegion());
// Shift the transformed region relative to the player
final Region shiftedRegion = regionHelper.shift(region,
location.getBlockX() - origin.getX(), location.getBlockY() - origin.getY(), location.getBlockZ() - origin.getZ());
drawManager.getDrawer(SelectionType.CUBOID).draw(player, shiftedRegion, DrawedType.CLIPBOARD);
} catch (final EmptyClipboardException ignored) {
// Ignore if there's no clipboard
}
drawClipboard(player, session);
}
// Selection
if (user.isSelectionShown()) {
final Region region;
try {
region = selector.getRegion();
} catch (final IncompleteRegionException ignored) {
// Clear cache if present
if (settings.cacheLocations()) {
user.clearCache(DrawedType.SELECTED);
}
continue;
}
drawSelection(selector, player, user);
}
}
}
final SelectionType selectionType = SelectionType.fromKey(selector.getTypeName());
if (selectionType != null) {
drawSelection(player, user, region, selectionType, DrawedType.SELECTED);
}
private void drawClipboard(final Player player, final LocalSession session) {
try {
final ClipboardHolder holder = session.getClipboard();
final Clipboard clipboard = holder.getClipboard();
final Location location = player.getLocation();
final SimpleVector origin = regionHelper.getOrigin(clipboard);
// Transform the clipboard if necessary
final Transform transform = holder.getTransform();
final Region region = transform.isIdentity() ? clipboard.getRegion() : regionHelper.transformAndReShift(holder, clipboard.getRegion());
// Shift the transformed region relative to the player
final Region shiftedRegion = regionHelper.shift(region,
location.getBlockX() - origin.getX(), location.getBlockY() - origin.getY(), location.getBlockZ() - origin.getZ());
drawManager.getDrawer(SelectionType.CUBOID).draw(player, shiftedRegion, DrawedType.CLIPBOARD);
} catch (final EmptyClipboardException ignored) {
// Ignore if there's no clipboard
}
}
private void drawSelection(final RegionSelector selector, final Player player, final User user) {
try {
final Region region = selector.getRegion();
final SelectionType selectionType = SelectionType.fromKey(selector.getTypeName());
if (selectionType != null) {
drawSelection(player, user, region, selectionType, DrawedType.SELECTED);
}
} catch (final IncompleteRegionException ignored) {
// Clear cache if present
if (settings.cacheLocations()) {
user.clearCache(DrawedType.SELECTED);
}
}
}
@@ -280,10 +326,9 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
location.setY(vector.getY());
location.setZ(vector.getZ());
if (settings.sendParticlesToAll(drawedType)) {
particleHelper.playEffectToAll(settings.getParticle(drawedType), settings.getOthersParticle(drawedType),
location, settings.getParticleViewDistance(), player);
particleHelper.playEffectToAll(settings.getParticle(drawedType), settings.getOthersParticle(drawedType), location, player);
} else {
particleHelper.playEffect(settings.getParticle(drawedType), location, settings.getParticleViewDistance(), player);
particleHelper.playEffect(settings.getParticle(drawedType), location, player);
}
}
return;
@@ -336,7 +381,7 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
return regionHelper;
}
@Nullable
@MonotonicNonNull
public ProtectedRegionHelper getProtectedRegionHelper() {
return protectedRegionHelper;
}
@@ -348,4 +393,13 @@ public final class WorldEditSUIPlugin extends JavaPlugin {
public boolean isWorldGuardEnabled() {
return worldGuardEnabled;
}
private static boolean hasClass(final String className) {
try {
Class.forName(className);
return true;
} catch (final ClassNotFoundException e) {
return false;
}
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -91,7 +91,7 @@ public final class WESUICommand implements CommandExecutor, TabCompleter {
settings.loadLanguageFile();
// Empty cache to recalculate positions
plugin.getUserManager().getUsers().values().forEach(User::clearCaches);
plugin.checkTasks();
plugin.reloadTasks();
sender.sendMessage(getMessage("reload"));
// Reset Bukkit's no perm message for the command
plugin.getCommand("worldeditsui").setPermissionMessage(settings.getMessage("noPermission"));
@@ -152,7 +152,7 @@ public final class WESUICommand implements CommandExecutor, TabCompleter {
sender.sendMessage(getMessage("helpToggleClipboard"));
if (plugin.isWorldGuardEnabled() && sender.hasPermission("wesui.command.showregion"))
sender.sendMessage(getMessage("helpShowRegion"));
sender.sendMessage("§8× §eVersion " + plugin.getVersion() + " §7by §bKennyTV");
sender.sendMessage("§8× §eVersion " + plugin.getVersion() + " §7by §bkennytv");
sender.sendMessage(getMessage("helpHeader"));
sender.sendMessage("");
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,6 +35,8 @@ public final class CuboidDrawer extends DrawerBase {
@Override
public void draw(final Player player, final Region region, final DrawedType drawedType) {
if (!hasValidSize(player, region)) return;
final double width = region.getWidth();
final double length = region.getLength();
final double height = region.getHeight();
@@ -50,9 +52,9 @@ public final class CuboidDrawer extends DrawerBase {
int gridSpaceZ = 0;
int topGridSpace = 0;
if (settings.hasAdvancedGrid(drawedType)) {
gridSpaceX = settings.getParticlesPerBlock() * ((int) ((width * height) / AREA_FACTOR) + 1);
gridSpaceZ = settings.getParticlesPerBlock() * ((int) ((length * height) / AREA_FACTOR) + 1);
topGridSpace = settings.getParticlesPerBlock() * ((int) ((width * length) / AREA_FACTOR) + 1);
gridSpaceX = settings.getParticlesPerBlock() * checkSpace(((int) ((width * height) / AREA_FACTOR) + 1));
gridSpaceZ = settings.getParticlesPerBlock() * checkSpace(((int) ((length * height) / AREA_FACTOR) + 1));
topGridSpace = settings.getParticlesPerBlock() * checkSpace(((int) ((width * length) / AREA_FACTOR) + 1));
maxGridTicks = height * settings.getParticlesPerGridBlock(drawedType) - 1;
maxTopGridTicksX = length * settings.getParticlesPerGridBlock(drawedType) - 1;
maxTopGridTicksZ = width * settings.getParticlesPerGridBlock(drawedType) - 1;
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +36,8 @@ public final class CylinderDrawer extends DrawerBase {
@Override
public void draw(final Player player, final Region region, final DrawedType drawedType) {
if (!hasValidSize(player, region)) return;
final SimpleVector radius = plugin.getRegionHelper().getRadius((CylinderRegion) region, 1.3, 1.3);
final int width = (int) radius.getX();
final int length = (int) radius.getZ();
@@ -65,7 +67,7 @@ public final class CylinderDrawer extends DrawerBase {
final double x = location.getX();
final double z = location.getZ();
final double bottom = location.getY();
final int gap = settings.getParticlesPerBlock() * (((width * length) / AREA_FACTOR) + 1);
final int gap = checkSpace(settings.getParticlesPerBlock() * (((width * length) / AREA_FACTOR) + 1));
final int ticks = 2 * (width - 1) / gap;
if (xAxis) {
location.setX(location.getX() - width);
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,8 +18,8 @@
package eu.kennytv.worldeditsui.drawer;
import eu.kennytv.worldeditsui.compat.SelectionType;
import eu.kennytv.worldeditsui.WorldEditSUIPlugin;
import eu.kennytv.worldeditsui.compat.SelectionType;
import eu.kennytv.worldeditsui.drawer.base.Drawer;
import java.util.HashMap;
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,6 +35,8 @@ public final class EllipsoidDrawer extends DrawerBase {
@Override
public void draw(final Player player, final Region region, final DrawedType drawedType) {
if (!hasValidSize(player, region)) return;
final SimpleVector radius = plugin.getRegionHelper().getRadius((EllipsoidRegion) region, 1.5, 1.4, 1.5);
final int width = (int) radius.getX();
final int length = (int) radius.getZ();
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +36,8 @@ public final class PolygonalDrawer extends DrawerBase {
@Override
public void draw(final Player player, final Region region, final DrawedType drawedType) {
if (!hasValidSize(player, region)) return;
final Polygonal2DRegion polyRegion = (Polygonal2DRegion) region;
final Simple2DVector[] points = plugin.getRegionHelper().getPoints(polyRegion);
Simple2DVector last = points[0];
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@ package eu.kennytv.worldeditsui.drawer.base;
import com.sk89q.worldedit.regions.Region;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public interface Drawer {
@@ -33,7 +32,7 @@ public interface Drawer {
* @param region region to be displayed with particles
* @param drawedType drawed type
*/
void draw(@Nullable Player player, Region region, DrawedType drawedType);
void draw(Player player, Region region, DrawedType drawedType);
/**
* Recreates the given with particles.
@@ -43,7 +42,7 @@ public interface Drawer {
* @param player player to send the particles to, may be null when sent to all players
* @param region region to be displayed with particles
*/
default void draw(@Nullable final Player player, final Region region) {
default void draw(final Player player, final Region region) {
draw(player, region, DrawedType.SELECTED);
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
package eu.kennytv.worldeditsui.drawer.base;
import com.sk89q.worldedit.regions.Region;
import eu.kennytv.worldeditsui.Settings;
import eu.kennytv.worldeditsui.WorldEditSUIPlugin;
import eu.kennytv.worldeditsui.compat.SimpleVector;
@@ -29,6 +30,7 @@ import org.bukkit.entity.Player;
public abstract class DrawerBase implements Drawer {
protected static final int MAX_GAP = 30;
protected static final int AREA_FACTOR = 256;
protected final WorldEditSUIPlugin plugin;
protected final Settings settings;
@@ -38,6 +40,12 @@ public abstract class DrawerBase implements Drawer {
this.settings = plugin.getSettings();
}
protected boolean hasValidSize(final Player player, final Region region) {
if (settings.getMaxSelectionSizeToDisplay() == 0) return true;
return region.getArea() <= settings.getMaxSelectionSizeToDisplay()
|| (settings.useMaxSelectionSizeBypassPerm() && player.hasPermission("wesui.maxselectionsize.bypass"));
}
protected void playEffect(final Location location, final Player player) {
playEffect(location, player, DrawedType.SELECTED);
}
@@ -54,9 +62,13 @@ public abstract class DrawerBase implements Drawer {
final ParticleData particle = settings.getParticle(drawedType);
if (settings.sendParticlesToAll(drawedType)) {
final ParticleData othersParticle = settings.getOthersParticle(drawedType);
plugin.getParticleHelper().playEffectToAll(particle, othersParticle, location, settings.getParticleViewDistance(), player);
plugin.getParticleHelper().playEffectToAll(particle, othersParticle, location, player);
} else {
plugin.getParticleHelper().playEffect(particle, location, settings.getParticleViewDistance(), player);
plugin.getParticleHelper().playEffect(particle, location, player);
}
}
protected int checkSpace(final int gap) {
return Math.min(gap, MAX_GAP);
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
package eu.kennytv.worldeditsui.listener;
import eu.kennytv.worldeditsui.WorldEditSUIPlugin;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
@@ -28,10 +31,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public final class PlayerJoinListener implements Listener {
private final Set<UUID> notified = new HashSet<>();
@@ -45,12 +44,13 @@ public final class PlayerJoinListener implements Listener {
public void playerJoin(final PlayerJoinEvent event) {
final Player player = event.getPlayer();
plugin.getUserManager().createUser(player);
if (!plugin.getSettings().hasUpdateChecks()) return;
if (!player.hasPermission("worldeditsui.admin")) return;
if (notified.contains(player.getUniqueId())) return;
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
if (!plugin.updateAvailable()) return;
plugin.runAsync(() -> {
if (!plugin.checkForLatestVersion()) return;
if (!player.isOnline()) return;
player.sendMessage(plugin.getPrefix() + "§cThere is a newer version available: §aVersion " + plugin.getNewestVersion() + "§c, you're on §a" + plugin.getDescription().getVersion());
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,254 +0,0 @@
package eu.kennytv.worldeditsui.metrics;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
/**
* bStats collects some data for plugin authors.
* <p>
* Check out https://bStats.org/ to learn more about bStats!
*/
public final class MetricsLite {
public static final int B_STATS_VERSION = 1;
private static final int PLUGIN_ID = 5444;
private static final String URL = "https://bStats.org/submitData/bukkit";
private final boolean enabled;
private static boolean logFailedRequests;
private static boolean logSentData;
private static boolean logResponseStatusText;
private static String serverUUID;
private final Plugin plugin;
public MetricsLite(final Plugin plugin) {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null!");
}
this.plugin = plugin;
final File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
final File configFile = new File(bStatsFolder, "config.yml");
final YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
if (!config.isSet("serverUuid")) {
config.addDefault("enabled", true);
config.addDefault("serverUuid", UUID.randomUUID().toString());
config.addDefault("logFailedRequests", false);
config.addDefault("logSentData", false);
config.addDefault("logResponseStatusText", false);
config.options().header(
"bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
"To honor their work, you should not disable it.\n" +
"This has nearly no effect on the server performance!\n" +
"Check out https://bStats.org/ to learn more :)"
).copyDefaults(true);
try {
config.save(configFile);
} catch (final IOException ignored) {
}
}
serverUUID = config.getString("serverUuid");
logFailedRequests = config.getBoolean("logFailedRequests", false);
enabled = config.getBoolean("enabled", true);
logSentData = config.getBoolean("logSentData", false);
logResponseStatusText = config.getBoolean("logResponseStatusText", false);
if (enabled) {
boolean found = false;
for (final Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION");
found = true;
break;
} catch (final NoSuchFieldException ignored) {
}
}
Bukkit.getServicesManager().register(MetricsLite.class, this, plugin, ServicePriority.Normal);
if (!found) {
startSubmitting();
}
}
}
public boolean isEnabled() {
return enabled;
}
private void startSubmitting() {
final Timer timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!plugin.isEnabled()) { // Plugin was disabled
timer.cancel();
return;
}
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
}
public JsonObject getPluginData() {
final JsonObject data = new JsonObject();
final String pluginName = plugin.getDescription().getName();
final String pluginVersion = plugin.getDescription().getVersion();
data.addProperty("pluginName", pluginName);
data.addProperty("id", PLUGIN_ID);
data.addProperty("pluginVersion", pluginVersion);
data.add("customCharts", new JsonArray());
return data;
}
private JsonObject getServerData() {
final int playerAmount = Bukkit.getOnlinePlayers().size();
final int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
final String bukkitVersion = Bukkit.getVersion();
final String bukkitName = Bukkit.getName();
final String javaVersion = System.getProperty("java.version");
final String osName = System.getProperty("os.name");
final String osArch = System.getProperty("os.arch");
final String osVersion = System.getProperty("os.version");
final int coreCount = Runtime.getRuntime().availableProcessors();
final JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bukkitVersion", bukkitVersion);
data.addProperty("bukkitName", bukkitName);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
private void submitData() {
final JsonObject data = getServerData();
final JsonArray pluginData = new JsonArray();
for (final Class<?> service : Bukkit.getServicesManager().getKnownServices()) {
try {
service.getField("B_STATS_VERSION");
for (final RegisteredServiceProvider<?> provider : Bukkit.getServicesManager().getRegistrations(service)) {
try {
final Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
} else {
try {
final Class<?> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
final Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
jsonStringGetter.setAccessible(true);
final String jsonString = (String) jsonStringGetter.invoke(plugin);
final JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
pluginData.add(object);
}
} catch (final ClassNotFoundException e) {
if (logFailedRequests) {
this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
}
}
}
} catch (final NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
}
} catch (final NoSuchFieldException ignored) {
}
}
data.add("plugins", pluginData);
new Thread(() -> {
try {
sendData(plugin, data);
} catch (final Exception e) {
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}).start();
}
private static void sendData(final Plugin plugin, final JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null!");
}
if (Bukkit.isPrimaryThread()) {
throw new IllegalAccessException("This method must not be called from the main thread!");
}
if (logSentData) {
plugin.getLogger().info("Sending data to bStats: " + data);
}
final HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
final byte[] compressedData = compress(data.toString());
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
connection.setDoOutput(true);
try (final DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(compressedData);
}
if (logResponseStatusText) {
final StringBuilder builder = new StringBuilder();
try (final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
plugin.getLogger().info("Sent data to bStats and received response: " + builder);
} else {
connection.getInputStream().close();
}
}
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (final GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,8 +18,8 @@
package eu.kennytv.worldeditsui.user;
import eu.kennytv.worldeditsui.compat.SimpleVector;
import eu.kennytv.worldeditsui.compat.SelectionType;
import eu.kennytv.worldeditsui.compat.SimpleVector;
import java.util.ArrayList;
import java.util.List;
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -58,7 +58,9 @@ public final class UserManager {
public void deleteUser(final Player player) {
final User removedUser = users.remove(player.getUniqueId());
removedUser.clearCaches();
if (removedUser != null) {
removedUser.clearCaches();
}
}
public Map<UUID, User> getUsers() {
@@ -0,0 +1,24 @@
/*
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.worldeditsui.util;
public interface Cancellable {
void cancel();
}
@@ -0,0 +1,34 @@
/*
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.worldeditsui.util;
import org.bukkit.scheduler.BukkitTask;
public final class CancellableBukkitTask implements Cancellable {
private final BukkitTask task;
public CancellableBukkitTask(final BukkitTask task) {
this.task = task;
}
@Override
public void cancel() {
task.cancel();
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.kennytv.worldeditsui.util;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
public final class CancellableScheduledTask implements Cancellable {
private final ScheduledTask task;
public CancellableScheduledTask(final ScheduledTask task) {
this.task = task;
}
@Override
public void cancel() {
task.cancel();
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,24 +30,30 @@ import org.jetbrains.annotations.Nullable;
public final class ParticleData {
private final Particle particle;
private final int radiusSquared;
private final double speed;
private final double offX;
private final double offY;
private final double offZ;
private final Object data;
public ParticleData(final Particle particle, @Nullable final Object data) {
public ParticleData(final Particle particle, final int radius) {
this(particle, radius, 0, 0, 0, 0, null);
}
public ParticleData(final Particle particle, final int radius, final double speed,
final double offX, final double offY, final double offZ, @Nullable final Object data) {
this.particle = particle;
this.radiusSquared = radius * radius;
this.data = data;
}
public Particle getParticle() {
return particle;
}
@Nullable
public Object getData() {
return data;
this.speed = speed;
this.offX = offX;
this.offY = offY;
this.offZ = offZ;
}
//TODO proper error handling/warnings
public static Object getExtraData(final Particle particle, final ConfigurationSection section) throws Exception {
public static Object getExtraData(final Particle particle, final ConfigurationSection section) {
final Class<?> dataType = particle.getDataType();
if (dataType == null || dataType == Void.class) return null;
@@ -55,7 +61,7 @@ public final class ParticleData {
final String name = dataType.getSimpleName();
// they might exist, they might not ¯\_(ツ)_/¯
// also it's only executed when (re)loading the config, so I think I might just get away with this method (prolly not worth doing extra modules for this)
// also it's only executed when (re)loading the config, so I might just get away with this method (not worth doing extra modules for this)
if (name.equals("DustOptions")) {
final float size = (float) section.getDouble("size");
final Color color = section.contains("rgb") ? Color.fromRGB(section.getInt("rgb"))
@@ -76,4 +82,33 @@ public final class ParticleData {
throw new IllegalArgumentException("The datatype " + name + " is not yet supported by the plugin - please report this error!");
}
public Particle getParticle() {
return particle;
}
public int radiusSquared() {
return radiusSquared;
}
public double speed() {
return speed;
}
public double offX() {
return offX;
}
public double offY() {
return offY;
}
public double offZ() {
return offZ;
}
@Nullable
public Object getData() {
return data;
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,34 +31,26 @@ public final class ParticleHelper {
this.settings = settings;
}
public void playEffect(final ParticleData particle, final Location location, final int radius, final Player player) {
playEffect(particle, location, 0, 0, 0, radius, player);
}
public void playEffect(final ParticleData particle, final Location location, final float offX, final float offY, final float offZ, final int radius, final Player player) {
public void playEffect(final ParticleData particle, final Location location, final Player player) {
if (!location.getWorld().equals(player.getWorld())) return;
final int radiusSquared = radius * radius;
if (player.getLocation().distanceSquared(location) > radiusSquared) return;
if (player.getLocation().distanceSquared(location) > particle.radiusSquared()) return;
player.spawnParticle(particle.getParticle(), location, 1, offX, offY, offZ, 0, particle.getData());
player.spawnParticle(particle.getParticle(), location, 1,
particle.offX(), particle.offY(), particle.offZ(), particle.speed(), particle.getData());
}
public void playEffectToAll(final ParticleData particle, final ParticleData othersParticle, final Location location, final int radius, final Player origin) {
playEffectToAll(particle, othersParticle, location, 0, 0, 0, radius, origin);
}
public void playEffectToAll(final ParticleData particle, final ParticleData othersParticle, final Location location, final float offX, final float offY, final float offZ, final int radius, final Player origin) {
final int radiusSquared = radius * radius;
public void playEffectToAll(final ParticleData particle, final ParticleData othersParticle, final Location location, final Player origin) {
for (final Player player : Bukkit.getOnlinePlayers()) {
if (!location.getWorld().equals(player.getWorld())
|| player.getLocation().distanceSquared(location) > radiusSquared) continue;
|| player.getLocation().distanceSquared(location) > particle.radiusSquared()) continue;
final boolean originalPlayer = player.getUniqueId().equals(origin.getUniqueId());
if (!originalPlayer && !canSeeOtherParticles(player)) continue;
final ParticleData toSend = originalPlayer ? particle : othersParticle;
player.spawnParticle(toSend.getParticle(), location, 1, offX, offY, offZ, 0, toSend.getData());
player.spawnParticle(toSend.getParticle(), location, 1,
particle.offX(), particle.offY(), particle.offZ(), particle.speed(), toSend.getData());
}
}
@@ -1,6 +1,6 @@
/*
* WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2020 KennyTV (https://github.com/KennyTV)
* This file is part of WorldEditSUI - https://git.io/wesui
* Copyright (C) 2018-2021 kennytv (https://github.com/kennytv)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+9 -1
View File
@@ -1,4 +1,4 @@
# WorldEditSUI Plugin by KennyTV
# WorldEditSUI Plugin by kennytv
# If enabled, the positions for particles will only be calculated once per selection and then cached.
# This essentially entirely removes the higher CPU usage of the calculations, but results in some caching if many/big selections are being made.
@@ -12,6 +12,7 @@ cache-calculated-positions: true
#
# If you want to use a particle that requires extra data (REDSTONE, FALLING_DUST, BLOCK_DUST, BLOCK_CRACK, ITEM_CRACK),
# you can read up on how to do that at the bottom of the plugin's Spigot page.
# The same applies to per-particle view-distance, speed, and offsets.
particle: FLAME
# Shown for the clipboard (after using WorldEdit's //copy command).
# Can be enabled with the '/wesui toggleclipboard' command.
@@ -32,6 +33,13 @@ particle-send-interval: 12
# Set this to -1 to disable.
max-ping: 150
# Selecting giant areas may result in a high cpu usage or server lag.
# This limits the maximum number of blocks that can be displayed (default is 10 million, ~250*150*250 blocks).
# You could still go even higher if they can only be used by trusted people.
max-selection-size-to-display: 10_000_000
# If set to true, players with the 'wesui.maxselectionsize.bypass' permission ignore the limit from above.
enable-max-selection-bypass-perm: true
advanced-grid:
# If enabled, the selection will not only be displayed by the outline,
# but also with a grid between the outlines (the bigger the selection, the bigger the grid).
+3 -2
View File
@@ -1,11 +1,12 @@
name: ${project.name}
name: WorldEditSUI
version: ${project.version}
main: eu.kennytv.worldeditsui.WorldEditSUIPlugin
authors: [KennyTV]
authors: [kennytv]
depend: [WorldEdit]
softdepend: [WorldGuard]
website: https://www.spigotmc.org/resources/worldeditsui.60726/
api-version: 1.13
folia-supported: true
commands:
worldeditsui: