Compare commits

...

2 Commits

3 changed files with 154 additions and 0 deletions

View File

@ -1,6 +1,7 @@
package com.alttd.playerutils; package com.alttd.playerutils;
import com.alttd.playerutils.commands.PlayerUtilsCommand; import com.alttd.playerutils.commands.PlayerUtilsCommand;
import com.alttd.playerutils.commands.playerutils_subcommands.AprilFools;
import com.alttd.playerutils.commands.playerutils_subcommands.GhastSpeed; import com.alttd.playerutils.commands.playerutils_subcommands.GhastSpeed;
import com.alttd.playerutils.commands.playerutils_subcommands.RotateBlock; import com.alttd.playerutils.commands.playerutils_subcommands.RotateBlock;
import com.alttd.playerutils.config.Config; import com.alttd.playerutils.config.Config;
@ -13,12 +14,17 @@ import org.bukkit.plugin.java.JavaPlugin;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.alttd.playerutils.util.AprilFoolsPrank;
public final class PlayerUtils extends JavaPlugin { public final class PlayerUtils extends JavaPlugin {
private PlayerUtilsCommand playerUtilsCommand; private PlayerUtilsCommand playerUtilsCommand;
private AprilFoolsPrank aprilFoolsPrank;
@Override @Override
public void onEnable() { public void onEnable() {
// initialize prank utility
aprilFoolsPrank = new AprilFoolsPrank(this);
registerCommands(); registerCommands();
registerEvents(); registerEvents();
reloadConfigs(); reloadConfigs();
@ -32,6 +38,8 @@ public final class PlayerUtils extends JavaPlugin {
private void registerCommands() { private void registerCommands() {
playerUtilsCommand = new PlayerUtilsCommand(this); playerUtilsCommand = new PlayerUtilsCommand(this);
// add april fools test command
playerUtilsCommand.addSubCommand(new AprilFools(aprilFoolsPrank));
} }
private void registerEvents() { private void registerEvents() {
@ -61,7 +69,11 @@ public final class PlayerUtils extends JavaPlugin {
} }
private void registerSchedulers() { private void registerSchedulers() {
// periodic key storage save (async)
Bukkit.getScheduler().runTaskTimerAsynchronously(this, KeyStorage.STORAGE::save, Bukkit.getScheduler().runTaskTimerAsynchronously(this, KeyStorage.STORAGE::save,
TimeUnit.MINUTES.toSeconds(5) * 20, TimeUnit.MINUTES.toSeconds(5) * 20); TimeUnit.MINUTES.toSeconds(5) * 20, TimeUnit.MINUTES.toSeconds(5) * 20);
// April 1st prank scheduler
aprilFoolsPrank.schedule();
} }
} }

View File

@ -0,0 +1,48 @@
package com.alttd.playerutils.commands.playerutils_subcommands;
import com.alttd.playerutils.commands.SubCommand;
import com.alttd.playerutils.config.Messages;
import com.alttd.playerutils.util.AprilFoolsPrank;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class AprilFools extends SubCommand {
private final AprilFoolsPrank prank;
public AprilFools(AprilFoolsPrank prank) {
this.prank = prank;
}
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (!(commandSender instanceof Player player)) {
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
return true;
}
boolean ok = prank.playSoundAroundPlayer(player);
if (ok) {
commandSender.sendRichMessage("<green>April Fools test triggered. Listen closely...");
} else {
commandSender.sendRichMessage("<red>Failed to trigger. You must be in the overworld named 'world'.");
}
return true;
}
@Override
public String getName() {
return "aprilfools";
}
@Override
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
return List.of();
}
@Override
public String getHelpMessage() {
return "<gray>/playerutils aprilfools</gray> <dark_gray>-</dark_gray> <gray>Play a fake explosion near you (testing).";
}
}

View File

@ -0,0 +1,94 @@
package com.alttd.playerutils.util;
import com.alttd.playerutils.PlayerUtils;
import lombok.extern.slf4j.Slf4j;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* Encapsulates the April Fools' prank logic. - schedule(): registers the timed prank that only runs on April 1st and
* only during overworld night. - playExplosionAround(Player): immediately plays the explosion sound around the target
* for testing (no date/time checks), but still requires the target to be in the overworld named "world" to match
* intended environment.
*/
@Slf4j
public class AprilFoolsPrank {
private final PlayerUtils plugin;
public AprilFoolsPrank(PlayerUtils plugin) {
this.plugin = plugin;
}
/**
* Register the timed prank task. Safe to call on the main thread during plugin enable.
*/
public void schedule() {
// April 1st prank: during overworld night, every 2 minutes pick one player and play an explosion somewhere in a 30-block radius
Bukkit.getScheduler().runTaskTimer(plugin, () -> {
LocalDate now = LocalDate.now(ZoneId.systemDefault());
if (now.getMonth() != Month.APRIL || now.getDayOfMonth() != 1) {
return; // only active on April 1st
}
World world = Bukkit.getWorld("world");
if (world == null) {
return; // overworld not present
}
List<Player> players = world.getPlayers();
if (players.isEmpty()) {
return;
}
Player target = players.get(ThreadLocalRandom.current().nextInt(players.size()));
playOnce(world, target);
}, 20L, 20L * 60L * 2L); // start after 1s, repeat every 2 minutes
}
/**
* Trigger the prank once around the given player for testing. Returns true if executed. This method ignores the
* date and time checks so it can be tested easily, but it still requires the player to be in the overworld named
* "world".
*/
public boolean playSoundAroundPlayer(Player target) {
if (target == null) {
return false;
}
World world = target.getWorld();
if (!"world".equalsIgnoreCase(world.getName())) {
return false; // only intended for overworld
}
playOnce(world, target);
return true;
}
public List<Sound> getSounds() {
return List.of(Sound.ENTITY_GENERIC_EXPLODE, Sound.BLOCK_BELL_USE, Sound.ENTITY_SPIDER_AMBIENT,
Sound.ENTITY_TNT_PRIMED, Sound.ENTITY_CAT_BEG_FOR_FOOD, Sound.ENTITY_SHULKER_AMBIENT,
Sound.BLOCK_WOODEN_DOOR_CLOSE);
}
private void playOnce(World world, Player target) {
Location base = target.getLocation();
double radius = 25.0;
double r = ThreadLocalRandom.current().nextDouble(radius);
double theta = ThreadLocalRandom.current().nextDouble(Math.PI * 2);
double dx = r * Math.cos(theta);
double dz = r * Math.sin(theta);
Location soundLoc = new Location(world, base.getX() + dx, base.getY(), base.getZ() + dz);
List<Sound> sounds = getSounds();
Sound chosen = sounds.get(ThreadLocalRandom.current().nextInt(sounds.size()));
log.info("Playing sound {} at {} (for {})", chosen, soundLoc, target.getName());
world.playSound(soundLoc, chosen, 1f, 1.0f);
}
}