Compare commits
9 Commits
ed0d15b3d4
...
b68835918f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b68835918f | ||
|
|
d3cd059af1 | ||
|
|
612a0281d6 | ||
|
|
d4f33b8c2e | ||
|
|
9fa43c8c65 | ||
|
|
13a78515c5 | ||
|
|
91e6d3be8e | ||
|
|
06a8aa0f65 | ||
|
|
139c51e9b8 |
|
|
@ -1,5 +1,6 @@
|
|||
package com.alttd.essentia;
|
||||
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public interface EssentiaAPI {
|
||||
|
|
@ -19,4 +20,6 @@ public interface EssentiaAPI {
|
|||
Provider.instance = instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void addLocationValidator(LocationValidator locationValidator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.alttd.essentia.api.model.randomteleport;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public interface LocationValidator {
|
||||
|
||||
boolean validate(Location location);
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
implementation(project(":api"))
|
||||
compileOnly("com.alttd:Galaxy-API:1.21.1-R0.1-SNAPSHOT")
|
||||
compileOnly("com.alttd.cosmos:cosmos-api:1.21.6-R0.1-SNAPSHOT")
|
||||
api("org.reflections:reflections:0.10.2")
|
||||
|
||||
compileOnly("org.projectlombok:lombok:1.18.34")
|
||||
|
|
|
|||
|
|
@ -2,11 +2,15 @@ package com.alttd.essentia;
|
|||
|
||||
import com.alttd.essentia.commands.EssentiaCommand;
|
||||
import com.alttd.essentia.configuration.Config;
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import com.alttd.essentia.feature.Features;
|
||||
import com.alttd.essentia.model.annotations.Depends;
|
||||
import com.alttd.essentia.storage.StorageManager;
|
||||
import com.alttd.essentia.storage.StorageProvider;
|
||||
import com.alttd.essentia.storage.StorageType;
|
||||
import com.alttd.essentia.user.EssentiaUserManager;
|
||||
import com.alttd.essentia.api.user.UserManager;
|
||||
import com.alttd.essentia.util.Timer;
|
||||
import io.papermc.paper.command.brigadier.Commands;
|
||||
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
|
||||
|
|
@ -18,6 +22,8 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.Scanners;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class EssentiaPlugin extends JavaPlugin implements EssentiaAPI {
|
||||
|
|
@ -27,10 +33,15 @@ public class EssentiaPlugin extends JavaPlugin implements EssentiaAPI {
|
|||
|
||||
@Getter
|
||||
private UserManager userManager;
|
||||
@Getter
|
||||
private List<LocationValidator> locationValidators;
|
||||
|
||||
@Getter
|
||||
private StorageProvider storageProvider;
|
||||
|
||||
@Getter
|
||||
private Features features;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
instance = this;
|
||||
|
|
@ -39,11 +50,15 @@ public class EssentiaPlugin extends JavaPlugin implements EssentiaAPI {
|
|||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
loadConfiguration();
|
||||
loadCommands();
|
||||
loadEventListeners();
|
||||
loadManagers();
|
||||
loadStorageProvider();
|
||||
new Timer("onEnable", () -> {
|
||||
new Timer("loadConfiguration", this::loadConfiguration);
|
||||
new Timer("loadFeatures", this::loadFeatures);
|
||||
new Timer("loadCommands", this::loadCommands);
|
||||
new Timer("loadEventListeners", this::loadEventListeners);
|
||||
new Timer("loadManagers", this::loadManagers);
|
||||
new Timer("loadStorageProvider", this::loadStorageProvider);
|
||||
new Timer("loadLocationValidators", this::loadLocationValidators);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -57,6 +72,11 @@ public class EssentiaPlugin extends JavaPlugin implements EssentiaAPI {
|
|||
Config.init();
|
||||
}
|
||||
|
||||
public void loadFeatures() {
|
||||
features = new Features(this);
|
||||
features.registerAll();
|
||||
}
|
||||
|
||||
void loadCommands() {
|
||||
Reflections reflections = new Reflections("com.alttd.essentia.commands");
|
||||
Set<Class<?>> subTypes = reflections.get(Scanners.SubTypes.of(EssentiaCommand.class).asClass());
|
||||
|
|
@ -67,6 +87,13 @@ public class EssentiaPlugin extends JavaPlugin implements EssentiaAPI {
|
|||
subTypes.forEach(clazz -> {
|
||||
try {
|
||||
EssentiaCommand essentiaCommand = (EssentiaCommand) clazz.getDeclaredConstructor().newInstance();
|
||||
final Depends depends = clazz.getAnnotation(Depends.class);
|
||||
if (depends != null) {
|
||||
if (!features.isEnabled(depends.value())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
commands.register(essentiaCommand.command(), essentiaCommand.description(), essentiaCommand.aliases());
|
||||
} catch (Exception e) {
|
||||
EssentiaPlugin.instance().getLogger().severe("Failed to register command " + clazz.getSimpleName());
|
||||
|
|
@ -100,4 +127,26 @@ public class EssentiaPlugin extends JavaPlugin implements EssentiaAPI {
|
|||
storageProvider.startAutoSaving();
|
||||
}
|
||||
|
||||
void loadLocationValidators() {
|
||||
this.locationValidators = new ArrayList<>();
|
||||
Reflections reflections = new Reflections("com.alttd.essentia.feature.randomteleport.validator");
|
||||
Set<Class<?>> subTypes = reflections.get(Scanners.SubTypes.of(LocationValidator.class).asClass());
|
||||
|
||||
subTypes.forEach(clazz -> {
|
||||
try {
|
||||
LocationValidator locationValidator = (LocationValidator) clazz.getDeclaredConstructor().newInstance();
|
||||
addLocationValidator(locationValidator);
|
||||
} catch (Exception e) {
|
||||
EssentiaPlugin.instance().getLogger().severe("Failed to add locationValidator " + clazz.getSimpleName());
|
||||
EssentiaPlugin.instance().getLogger().severe(e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO -- make this reload proof for API
|
||||
@Override
|
||||
public void addLocationValidator(LocationValidator locationValidator) {
|
||||
locationValidators.add(locationValidator);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package com.alttd.essentia.commands.admin;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.commands.EssentiaCommand;
|
||||
import com.alttd.essentia.request.RandomTeleportRequest;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import io.papermc.paper.command.brigadier.Commands;
|
||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
|
||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RandomTeleportCommand implements EssentiaCommand {
|
||||
|
||||
@Override
|
||||
public String commandName() {
|
||||
return "randomteleport";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull LiteralCommandNode<CommandSourceStack> command() {
|
||||
final LiteralArgumentBuilder<CommandSourceStack> builder =
|
||||
Commands.literal(commandName())
|
||||
.requires(commandSourceStack -> commandSourceStack.getSender().hasPermission(adminCommandPermission()))
|
||||
.then(
|
||||
Commands.argument("player", ArgumentTypes.player())
|
||||
.requires(commandSourceStack -> commandSourceStack.getSender().hasPermission(adminOtherCommandPermission()))
|
||||
.executes((source) -> {
|
||||
CommandSourceStack sourceStack = source.getSource();
|
||||
Player target = source.getArgument("player", PlayerSelectorArgumentResolver.class).resolve(sourceStack).getFirst();
|
||||
execute(source.getSource().getSender(), target);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Teleport a player to a random location!";
|
||||
}
|
||||
|
||||
public void execute(CommandSender sender, Player target) { // TODO - messages
|
||||
TagResolver placeholders = TagResolver.resolver(
|
||||
Placeholder.component("requester", sender.name()),
|
||||
Placeholder.component("target", target.displayName())
|
||||
);
|
||||
|
||||
new RandomTeleportRequest(EssentiaPlugin.instance(), target, target);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.alttd.essentia.configuration;
|
|||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.google.common.base.Throwables;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
|
@ -34,7 +36,7 @@ public class Config {
|
|||
config.load(CONFIG_FILE);
|
||||
} catch (IOException ignore) {
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
EssentiaPlugin.instance().getLogger().log(Level.SEVERE, "Could not load config.yml, please correct your syntax errors", ex);
|
||||
log(Level.SEVERE, "Could not load config.yml, please correct your syntax errors", ex);
|
||||
Throwables.throwIfUnchecked(ex);
|
||||
}
|
||||
config.options().header(HEADER);
|
||||
|
|
@ -43,7 +45,7 @@ public class Config {
|
|||
version = getInt("config-version", 1);
|
||||
set("config-version", 1);
|
||||
|
||||
EssentiaPlugin.instance().getLogger().info("Essentia Configuration loaded!");
|
||||
log(Level.INFO,"Essentia Configuration loaded!");
|
||||
readConfig(Config.class, null);
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +59,7 @@ public class Config {
|
|||
} catch (InvocationTargetException ex) {
|
||||
Throwables.throwIfUnchecked(ex);
|
||||
} catch (Exception ex) {
|
||||
EssentiaPlugin.instance().getLogger().log(Level.SEVERE, "Error invoking " + method, ex);
|
||||
log(Level.SEVERE, "Error invoking " + method, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +71,7 @@ public class Config {
|
|||
try {
|
||||
config.save(CONFIG_FILE);
|
||||
} catch (IOException ex) {
|
||||
EssentiaPlugin.instance().getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex);
|
||||
log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +109,10 @@ public class Config {
|
|||
EssentiaPlugin.instance().getLogger().log(level, s);
|
||||
}
|
||||
|
||||
protected static void log(Level level, String s, Throwable thrown) {
|
||||
EssentiaPlugin.instance().getLogger().log(level, s, thrown);
|
||||
}
|
||||
|
||||
public static int TELEPORT_REQUEST_TIMEOUT = 30;
|
||||
public static boolean TELEPORT_REQUEST_TIMEOUT_MESSAGES = true;
|
||||
public static boolean BACK_ON_DEATH = false;
|
||||
|
|
@ -270,4 +276,10 @@ public class Config {
|
|||
MYSQL_PASSWORD = getString("storage.mysql.password", MYSQL_PASSWORD);
|
||||
}
|
||||
|
||||
public static Object2BooleanMap<String> enabledFeatures = new Object2BooleanOpenHashMap<>();
|
||||
private static void features() {
|
||||
enabledFeatures.clear();
|
||||
enabledFeatures.defaultReturnValue(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package com.alttd.essentia.feature;
|
||||
|
||||
public interface EssentiaFeature {
|
||||
|
||||
String featureName();
|
||||
|
||||
void register();
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
default void start() {}
|
||||
|
||||
default void stop() {}
|
||||
|
||||
default void reload() {
|
||||
stop();
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package com.alttd.essentia.feature;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.configuration.Config;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.Scanners;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class Features {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
private final Map<String, EssentiaFeature> features;
|
||||
|
||||
public Features(EssentiaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
features = new HashMap<>();
|
||||
}
|
||||
|
||||
public boolean isEnabled(String featureName) {
|
||||
if (features.containsKey(featureName)) {
|
||||
return features.get(featureName).isEnabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void registerAll() {
|
||||
Reflections reflections = new Reflections("com.alttd.essentia.feature");
|
||||
Set<Class<?>> subTypes = reflections.get(Scanners.SubTypes.of(EssentiaFeature.class).asClass());
|
||||
|
||||
subTypes.forEach(clazz -> {
|
||||
try {
|
||||
EssentiaFeature essentiaFeature = (EssentiaFeature) clazz.getDeclaredConstructor().newInstance();
|
||||
if (!Config.enabledFeatures.getBoolean(essentiaFeature.featureName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
essentiaFeature.register();
|
||||
essentiaFeature.reload();
|
||||
|
||||
features.putIfAbsent(essentiaFeature.featureName(), essentiaFeature);
|
||||
} catch (Exception e) {
|
||||
log(Level.SEVERE,"Failed to register feature " + clazz.getSimpleName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void log(Level level, String s) {
|
||||
plugin.getLogger().log(level, s);
|
||||
}
|
||||
|
||||
protected void log(Level level, String s, Throwable thrown) {
|
||||
plugin.getLogger().log(level, s, thrown);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.alttd.essentia.feature.cuff;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.feature.EssentiaFeature;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
public class CuffFeature implements EssentiaFeature {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
public CuffFeature() {
|
||||
this.plugin = EssentiaPlugin.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String featureName() {
|
||||
return "cuff";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
final PluginManager pluginManager = plugin.getServer().getPluginManager();
|
||||
pluginManager.registerEvents(new CuffListener(), plugin);
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.alttd.essentia.listeners;
|
||||
package com.alttd.essentia.feature.cuff;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.api.user.User;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.alttd.essentia.feature.flight;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.feature.EssentiaFeature;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
public class FlightFeature implements EssentiaFeature {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
public FlightFeature() {
|
||||
this.plugin = EssentiaPlugin.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String featureName() {
|
||||
return "flight";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
final PluginManager pluginManager = plugin.getServer().getPluginManager();
|
||||
pluginManager.registerEvents(new FlightListener(), plugin);
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.alttd.essentia.listeners;
|
||||
package com.alttd.essentia.feature.flight;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.api.model.UserSettings;
|
||||
|
|
@ -8,7 +8,7 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
|
||||
// TODO -- set flight and flying when player logs in!
|
||||
public class FlightListener implements Listener {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.alttd.essentia.feature.godmode;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.api.model.UserSettings;
|
||||
import com.alttd.essentia.api.user.User;
|
||||
import com.alttd.essentia.api.user.UserManager;
|
||||
import com.alttd.essentia.feature.EssentiaFeature;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
public class GodModeFeature implements EssentiaFeature {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
public GodModeFeature() {
|
||||
this.plugin = EssentiaPlugin.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String featureName() {
|
||||
return "GodMode";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
final PluginManager pluginManager = plugin.getServer().getPluginManager();
|
||||
pluginManager.registerEvents(new GodModeListener(this), plugin);
|
||||
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
protected boolean isGodModeEnabled(Player player) {
|
||||
UserManager userManager = plugin.userManager();
|
||||
User user = userManager.getUser(player);
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
UserSettings userSettings = user.getUserSettings();
|
||||
return userSettings.godMode();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package com.alttd.essentia.feature.godmode;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.*;
|
||||
|
||||
public class GodModeListener implements Listener {
|
||||
|
||||
private GodModeFeature godModeFeature;
|
||||
public GodModeListener(GodModeFeature godModeFeature) {
|
||||
this.godModeFeature = godModeFeature;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPhantomPreSpawn(PhantomPreSpawnEvent event) {
|
||||
if (!(event.getSpawningEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
event.setShouldAbortSpawn(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityTargetLivingEntity(EntityTargetLivingEntityEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPotionSplashEvent(PotionSplashEvent event) {
|
||||
for (LivingEntity entity : event.getAffectedEntities()) {
|
||||
if (!(entity instanceof Player player))
|
||||
continue;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setIntensity(player, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onEntityCombustByEntityEvent(EntityCombustByEntityEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityCombust(final EntityCombustEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityDamage(final EntityDamageEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!isGodModeEnabled(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
private boolean isGodModeEnabled(Player player) {
|
||||
return godModeFeature.isGodModeEnabled(player);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.alttd.essentia.feature.randomteleport;
|
||||
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
// TODO - load biomes from config
|
||||
public class BiomeValidator implements LocationValidator {
|
||||
|
||||
private final boolean whitelist;
|
||||
private final Set<Biome> biomes;
|
||||
|
||||
public BiomeValidator() {
|
||||
this.biomes = new HashSet<>();
|
||||
this.whitelist = false;
|
||||
this.biomes.add(Biome.OCEAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(Location location) {
|
||||
Block block = location.getBlock();
|
||||
return biomes.contains(block.getBiome()) == whitelist;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.alttd.essentia.feature.randomteleport;
|
||||
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
// TODO - load block list from config
|
||||
public class BlockValidator implements LocationValidator {
|
||||
|
||||
private final boolean whitelist;
|
||||
private final Set<Material> materials;
|
||||
|
||||
public BlockValidator() {
|
||||
materials = new HashSet<>();
|
||||
this.whitelist = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(Location location) {
|
||||
Block block = location.getBlock();
|
||||
return materials.contains(block.getType()) == whitelist;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.alttd.essentia.feature.randomteleport;
|
||||
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import org.bukkit.Location;
|
||||
|
||||
// TODO - claim hooks for GP. LandClaims should hook into the plugin and add the validator.
|
||||
public class ProtectionValidator implements LocationValidator {
|
||||
|
||||
@Override
|
||||
public boolean validate(Location location) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.alttd.essentia.feature.randomteleport;
|
||||
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class WorldBorderValidator implements LocationValidator {
|
||||
|
||||
@Override
|
||||
public boolean validate(Location location) {
|
||||
return location.getWorld().getWorldBorder().isInside(location);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
package com.alttd.essentia.listeners;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.api.model.UserSettings;
|
||||
import com.alttd.essentia.api.user.User;
|
||||
import com.alttd.essentia.api.user.UserManager;
|
||||
import com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
|
||||
public class GodModeListener implements Listener {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
|
||||
public GodModeListener() {
|
||||
this.plugin = EssentiaPlugin.instance();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!hasGodMode(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void onPhantomPreSpawn(PhantomPreSpawnEvent event) {
|
||||
if (!(event.getSpawningEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!hasGodMode(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
event.setShouldAbortSpawn(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityTargetLivingEntity(EntityTargetLivingEntityEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
|
||||
if (!hasGodMode(player))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
private boolean hasGodMode(Player player) {
|
||||
UserManager userManager = plugin.userManager();
|
||||
User user = userManager.getUser(player);
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
UserSettings userSettings = user.getUserSettings();
|
||||
return userSettings.godMode();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.alttd.essentia.model.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Depends {
|
||||
String value();
|
||||
}
|
||||
|
|
@ -12,10 +12,10 @@ import org.bukkit.entity.Player;
|
|||
|
||||
public abstract class EssentiaRequest implements Request {
|
||||
|
||||
private final EssentiaPlugin plugin;
|
||||
protected final EssentiaPlugin plugin;
|
||||
@Getter private final Player requester;
|
||||
@Getter private final Player target;
|
||||
private final RequestTimeout timeoutTask;
|
||||
@Getter private final RequestTimeout timeoutTask;
|
||||
|
||||
TagResolver placeholders;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
package com.alttd.essentia.request;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
import com.alttd.essentia.api.model.randomteleport.LocationValidator;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class RandomTeleportRequest extends EssentiaRequest {
|
||||
|
||||
private static final List<int[]> CHUNK_POS = new ArrayList<>();
|
||||
private final Multimap<Integer, Integer> checked = MultimapBuilder.hashKeys().hashSetValues().build();
|
||||
|
||||
private final Random random;
|
||||
private final Location center; // todo - config
|
||||
private final int minRadius; // todo - config
|
||||
private final int maxRadius; // todo - config
|
||||
private final int maxTries = 100; // TODO - config
|
||||
|
||||
private int checks;
|
||||
CompletableFuture<Location> future;
|
||||
|
||||
static {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
CHUNK_POS.add(new int[]{x, z});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RandomTeleportRequest(EssentiaPlugin plugin, Player requester, Player target) {
|
||||
super(plugin, requester, target);
|
||||
this.random = new Random();
|
||||
this.center = Bukkit.getWorlds().getFirst().getSpawnLocation(); // todo - config and sanity check for worlds
|
||||
this.minRadius = 50;
|
||||
this.maxRadius = 20000;
|
||||
|
||||
this.timeoutTask().cancel();
|
||||
this.teleport();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start searching for a safe random location within the world
|
||||
*
|
||||
* @return A CompletableFuture for when the searching is finished.
|
||||
*/
|
||||
public CompletableFuture<Location> startSearch() {
|
||||
future = new CompletableFuture<>();
|
||||
target().sendRichMessage("Running search task");
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> searchRandomLocation(future));
|
||||
return future;
|
||||
}
|
||||
|
||||
// needs to be a task
|
||||
private void searchRandomLocation(CompletableFuture<Location> future) {
|
||||
if (future.isCancelled() || future.isDone() || future.isCompletedExceptionally()) {
|
||||
return;
|
||||
}
|
||||
Location randomLoc = center.clone();
|
||||
int minChunk = minRadius >> 4;
|
||||
int maxChunk = maxRadius >> 4;
|
||||
int randChunkX;
|
||||
int randChunkZ;
|
||||
|
||||
do {
|
||||
checks++;
|
||||
if (checks >= maxTries) {
|
||||
future.completeExceptionally(new Exception("Could not find random location within %s tries".formatted(maxTries + "")));
|
||||
return;
|
||||
}
|
||||
randChunkX = (random.nextBoolean() ? 1 : -1) * random.nextInt(maxChunk + 1);
|
||||
randChunkZ = (random.nextBoolean() ? 1 : -1) * random.nextInt(maxChunk + 1);
|
||||
target().sendRichMessage("randChunkX: " + randChunkX + ", randChunkZ: " + randChunkZ);
|
||||
} while (!checked.put(randChunkX, randChunkZ)
|
||||
|| !inRadius(Math.abs(randChunkX), Math.abs(randChunkZ), minChunk, maxChunk)
|
||||
/*|| randomLoc.getWorld().isChunkGenerated(randChunkX, randChunkZ)*/);
|
||||
|
||||
|
||||
randomLoc.setX(((center.getBlockX() >> 4) + randChunkX) * 16);
|
||||
randomLoc.setZ(((center.getBlockZ() >> 4) + randChunkZ) * 16);
|
||||
randomLoc.getWorld().getChunkAtAsync(randomLoc).thenApply(chunk -> {
|
||||
if (chunk == null) {
|
||||
searchRandomLocation(future);
|
||||
return false;
|
||||
}
|
||||
chunk.addPluginChunkTicket(plugin);
|
||||
try {
|
||||
int indexOffset = random.nextInt(CHUNK_POS.size());
|
||||
Location foundLoc = null;
|
||||
for (int i = 0; i < CHUNK_POS.size(); i++) {
|
||||
int index = (i + indexOffset) % CHUNK_POS.size();
|
||||
boolean validated = true;
|
||||
Location loc = randomLoc.clone().add(CHUNK_POS.get(index)[0], 0, CHUNK_POS.get(index)[1]);
|
||||
|
||||
if (!inRadius(loc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (LocationValidator validator : plugin.locationValidators()) {
|
||||
if (!validator.validate(loc)) {
|
||||
validated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (validated) {
|
||||
foundLoc = loc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundLoc != null) {
|
||||
// all checks are for the top block, put we want a location above that so add 1 to y
|
||||
future.complete(foundLoc.add(0, 1, 0));
|
||||
return true;
|
||||
}
|
||||
plugin.getServer().getScheduler().runTaskLater(plugin, () -> searchRandomLocation(future), 1);
|
||||
return false;
|
||||
} finally {
|
||||
chunk.removePluginChunkTicket(plugin);
|
||||
}
|
||||
}).exceptionally(future::completeExceptionally);
|
||||
}
|
||||
|
||||
private boolean inRadius(Location location) {
|
||||
int diffX = Math.abs(location.getBlockX() - center.getBlockX());
|
||||
int diffZ = Math.abs(location.getBlockZ() - center.getBlockZ());
|
||||
return inRadius(diffX, diffZ, minRadius, maxRadius);
|
||||
}
|
||||
|
||||
private boolean inRadius(int diffX, int diffZ, int minRadius, int maxRadius) {
|
||||
return diffX >= minRadius && diffX <= maxRadius && diffZ <= maxRadius
|
||||
|| diffZ >= minRadius && diffZ <= maxRadius && diffX <= maxRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void teleport() {
|
||||
startSearch().thenApply(randomLocation -> {
|
||||
randomLocation.setX(randomLocation.getBlockX() + 0.5);
|
||||
randomLocation.setY(randomLocation.getY() + 0.5);
|
||||
randomLocation.setZ(randomLocation.getBlockZ() + 0.5);
|
||||
target().teleportAsync(randomLocation)
|
||||
.whenComplete((success, exception) -> {
|
||||
target().sendMessage("You have been teleported to a random location."); // todo -- config
|
||||
});
|
||||
return true;
|
||||
});
|
||||
if (!target().isOnline() || !requester().isOnline()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
try {
|
||||
timeoutTask().cancel();
|
||||
} catch (IllegalStateException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
17
plugin/src/main/java/com/alttd/essentia/util/Timer.java
Normal file
17
plugin/src/main/java/com/alttd/essentia/util/Timer.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package com.alttd.essentia.util;
|
||||
|
||||
import com.alttd.essentia.EssentiaPlugin;
|
||||
|
||||
public class Timer {
|
||||
|
||||
public Timer(String id, Runnable runnable) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
runnable.run();
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
|
||||
EssentiaPlugin.instance().getLogger().info("Loading " + id + " took " + duration + "ms");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ name: Essentia
|
|||
version: ${version}
|
||||
main: com.alttd.essentia.EssentiaPlugin
|
||||
description: Altitude essentials ;)
|
||||
load: POSTWORLD
|
||||
authors:
|
||||
- destro174
|
||||
api-version: "1.21"
|
||||
Loading…
Reference in New Issue
Block a user