Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 1.6.0
Improve performances.
Save user settings on the Minecraft world.
Add an option to disable the light lock message.

# 1.5.0
Fix translation & add French translation.

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = "github.xCykrix"
version = "1.5.1"
version = "1.6.0"
description="Dynamic Lights for Minecraft Servers without requiring Modding."
val mainMinecraftVersion = "1.21.11"
val supportedMinecraftVersions = "1.21.11 - 1.21.11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import github.xCykrix.dynamicLights.DynamicLights;
import github.xCykrix.dynamicLights.util.PlayerUtil;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
Expand All @@ -16,6 +17,7 @@
@CommandAlias("dynamiclights|dynamiclight|dl")
public class DynamicLightsCommand extends co.aikar.commands.BaseCommand {// extends DevkitSimpleState {


private static JavaPlugin plugin;

public DynamicLightsCommand(JavaPlugin plugin) { this.plugin = plugin; }
Expand Down Expand Up @@ -52,15 +54,13 @@ public static String getStackTrace(Throwable throwable) {
@CommandPermission("dynamiclights.toggle")
public static void onToggle(CommandSender commandSender) {
if (commandSender instanceof Player player) {
String uuid = player.getUniqueId().toString();
boolean current = DynamicLights.manager.toggles.getOrDefault(uuid, DynamicLights.manager.toggle);
if (!current) {
player.sendMessage(DynamicLights.translate("toggle-on"));
DynamicLights.manager.toggles.put(uuid, true);
} else {
if (PlayerUtil.getToggleStatus(player)) {
player.sendMessage(DynamicLights.translate("toggle-off"));
DynamicLights.manager.toggles.put(uuid, false);
} else {
player.sendMessage(DynamicLights.translate("toggle-on"));
}

PlayerUtil.switchToggleStatus(player);
}
}

Expand All @@ -69,15 +69,27 @@ public static void onToggle(CommandSender commandSender) {
@CommandPermission("dynamiclights.lock")
public static void onLock(CommandSender commandSender) {
if (commandSender instanceof Player player) {
String uuid = player.getUniqueId().toString();
boolean current = DynamicLights.manager.locks.getOrDefault(uuid, true);
if (!current) {
if (PlayerUtil.getLockStatus(player)) {
player.sendMessage(DynamicLights.translate("disable-lock"));
} else {
player.sendMessage(DynamicLights.translate("enable-lock"));
DynamicLights.manager.locks.put(uuid, true);
}

PlayerUtil.switchLockStatus(player);
}
}
@Subcommand("lockverbose")
@Description("Make the warning lock message go away")
@CommandPermission("dynamiclights.lock")
public static void onLockVerbose(CommandSender commandSender) {
if (commandSender instanceof Player player) {
if (PlayerUtil.getLockStatus(player)) {
player.sendMessage(DynamicLights.translate("disable-lock-verbose"));
} else {
player.sendMessage(DynamicLights.translate("disable-lock"));
DynamicLights.manager.locks.put(uuid, false);
player.sendMessage(DynamicLights.translate("enable-lock-verbose"));
}

PlayerUtil.switchLockVerboseStatus(player);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package github.xCykrix.dynamicLights.event;

import github.xCykrix.dynamicLights.DynamicLights;
import github.xCykrix.dynamicLights.util.PlayerUtil;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.plugin.java.JavaPlugin;
Expand All @@ -22,21 +25,30 @@ public void playerBlockPlaceEvent(BlockPlaceEvent event) {
if (!DynamicLights.source.isProtectedLight(event.getItemInHand().getType())) {
return;
}
if (DynamicLights.manager.locks.getOrDefault(event.getPlayer().getUniqueId().toString(), DynamicLights.manager.toggle)) {
event.getPlayer().sendMessage(DynamicLights.translate("prevent-block-place"));
if (PlayerUtil.getLockStatus(event.getPlayer())) {
// send a text to the player to explain why the block place event was cancelled
if (PlayerUtil.getLockVerboseStatus(event.getPlayer())) {
event.getPlayer().sendMessage(DynamicLights.translate("prevent-block-place"));
}
// cancel the event
event.setCancelled(true);
}
}
}

// No need we do it for each online player
// @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
// public void onPlayerJoinEvent(PlayerJoinEvent event) {
// DynamicLights.manager.addPlayer(event.getPlayer());
// }

@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuitEvent(PlayerQuitEvent event) {
DynamicLights.manager.removeLightFromLocationRegion(event.getPlayer().getUniqueId());
DynamicLights.manager.removePlayerLightEnabled(event.getPlayer().getUniqueId());
// DynamicLights.manager.removeLightFromLocationRegion(event.getPlayer().getUniqueId());
}

@EventHandler(ignoreCancelled = true)
public void onPlayerGameModeChangeEvent(PlayerGameModeChangeEvent event) {
DynamicLights.manager.updatePlayerState(event.getPlayer(), event.getNewGameMode());
}

@EventHandler
public void onPlayerJoinEvent(PlayerJoinEvent event) {
DynamicLights.manager.updatePlayerState(event.getPlayer(), event.getPlayer().getGameMode());
}
}
70 changes: 33 additions & 37 deletions src/main/java/github/xCykrix/dynamicLights/util/LightManager.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package github.xCykrix.dynamicLights.util;

import github.xCykrix.dynamicLights.DynamicLights;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
Expand All @@ -25,52 +24,59 @@ public class LightManager {
private final LightSource source;
private final Map<UUID, Location> lastLightLocation = new ConcurrentHashMap<>(200);

public final ConcurrentMap<String, Boolean> toggles;
public final ConcurrentMap<String, Boolean> locks;
private final long refresh;
public final boolean toggle;
private final Set<UUID> playerLightEnabled;

private JavaPlugin plugin;

public LightManager(JavaPlugin plugin) {
this.plugin = plugin;
// YamlDocument config = DynamicLights.configuration.getYAMLFile("config.yml");
// if (config == null) {
// throw new RuntimeException("config.yml is corrupted or contains invalid formatting. Failed to load plugin.");
// }

this.source = DynamicLights.source;
// TODO reenable file storing of toggles & locks
// this.toggles = DynamicLights.h2.get().openMap("lightToggleStatus");
// this.locks = DynamicLights.h2.get().openMap("lightLockStatus");
this.toggles = new ConcurrentHashMap<>();
this.locks = new ConcurrentHashMap<>();
this.refresh = plugin.getConfig().getLong("update-rate");
this.toggle = plugin.getConfig().getBoolean("default-toggle-state");

// this.lights = Collections.synchronizedList(new LinkedList<>());
playerLightEnabled = ConcurrentHashMap.newKeySet();

Bukkit.getAsyncScheduler().runAtFixedRate(plugin, st -> tick(), 0L, refresh, TimeUnit.MILLISECONDS);
Bukkit.getAsyncScheduler().runAtFixedRate(plugin, st -> tick(), 0L, plugin.getConfig().getLong("update-rate"), TimeUnit.MILLISECONDS);
}


// @Override
public void shutdown() { clearAllLights(); }

public void addPlayerLightEnabled(UUID uuid) { playerLightEnabled.add(uuid); }

public void removePlayerLightEnabled(UUID uuid) { playerLightEnabled.remove(uuid); }

public boolean isPlayerLightEnabled(UUID uuid) { return playerLightEnabled.contains(uuid); }

// Player emit light if (SURVIVAL or ADVENTURE) and they have it enabled.
public void updatePlayerState(Player player, GameMode mode) {
if ((mode == GameMode.SURVIVAL || mode == GameMode.ADVENTURE) && PlayerUtil.getToggleStatus(player)) {
addPlayerLightEnabled(player.getUniqueId());
} else {
removePlayerLightEnabled(player.getUniqueId());
// removeLightFromLocationRegion(player.getUniqueId());
}
}

public void tick() {
if (!plugin.isEnabled()) {
clearAllLights();
return;
}

// For each online player, check if we should add a light or move the existing one
Collection<? extends Player> players = Bukkit.getOnlinePlayers();
for (Player targetPlayer : players) {
updatePlayerLight(targetPlayer);
// For each online player that have the right game mode, check if we should add a light or move the existing one
for (UUID targetPlayerUUID : playerLightEnabled) {
updatePlayerLight(Bukkit.getPlayer(targetPlayerUUID));
}

// Removing player light when the player quit is now done in player quit event.
// Remove each light that should not be there
// With a short delay between each tick(), the light is added back when removed from somewhere else,
// so we need to remove it after the main for loop.
// It might call to remove the light many time if the region scheduler is not fast enough, but it's fine I guess.
for (UUID targetPlayerUUID : lastLightLocation.keySet()) {
if (!playerLightEnabled.contains(targetPlayerUUID)) {
this.removeLightFromLocationRegion(targetPlayerUUID);
}
}
}

public void clearAllLights() {
Expand All @@ -88,17 +94,6 @@ public void updatePlayerLight(Player player) {
* Find the best location to place a light and update the light if needed.
*/
private Optional<Location> updateLightToNewLocation(Player player, Location eyeLocation) {
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) {
// plugin.getLogger().info("creative or spectator");
this.removeLightFromLocationRegion(player.getUniqueId());
return Optional.empty();
}
if (!(this.toggles.getOrDefault(player.getUniqueId().toString(), this.toggle))) {
this.removeLightFromLocationRegion(player.getUniqueId());
return Optional.empty();
}


Material mainHand = getMaterialOrAir(player.getInventory().getItemInMainHand());
Material offHand = getMaterialOrAir(player.getInventory().getItemInOffHand());
Material helmet = getMaterialOrAir(player.getInventory().getHelmet());
Expand Down Expand Up @@ -201,7 +196,8 @@ private void removeLight(UUID playerUuid, Location location) {
}
}
}
// Remove only if its the current last location, else we want to keep that value to remove it later when we will have to remove the light.
// Remove only if its the current last location, else we want to keep that value to remove it later when we will have to remove the
// light.
lastLightLocation.remove(playerUuid, location);
// DynamicLights.getInstance().getLogger().info("Removed light at " + location);
}
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/github/xCykrix/dynamicLights/util/PlayerUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package github.xCykrix.dynamicLights.util;

import github.xCykrix.dynamicLights.DynamicLights;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;

public class PlayerUtil {
private static NamespacedKey lightToggleStatusKey = new NamespacedKey("dynamiclights", "toggle-state");
private static NamespacedKey lightLockStatusKey = new NamespacedKey("dynamiclights", "lock-state");
private static NamespacedKey lightLockVerboseStatusKey = new NamespacedKey("dynamiclights", "lock-verbose-state");
public static boolean getToggleStatus(Player player) {
return player.getPersistentDataContainer().getOrDefault(lightToggleStatusKey, PersistentDataType.BOOLEAN,
DynamicLights.getInstance().getConfig().getBoolean("default-toggle-state", true));
}
public static void switchToggleStatus(Player player) {
player.getPersistentDataContainer().set(lightToggleStatusKey, PersistentDataType.BOOLEAN, !getToggleStatus(player));
}

public static boolean getLockStatus(Player player) {
return player.getPersistentDataContainer().getOrDefault(lightLockStatusKey, PersistentDataType.BOOLEAN,
DynamicLights.getInstance().getConfig().getBoolean("default-lock-state", false));
}

public static void switchLockStatus(Player player) {
player.getPersistentDataContainer().set(lightLockStatusKey, PersistentDataType.BOOLEAN, !getLockStatus(player));
}

public static boolean getLockVerboseStatus(Player player) {
return player.getPersistentDataContainer().getOrDefault(lightLockVerboseStatusKey, PersistentDataType.BOOLEAN,
DynamicLights.getInstance().getConfig().getBoolean("default-lock-verbose-state", true));
}

public static void switchLockVerboseStatus(Player player) {
player.getPersistentDataContainer().set(lightLockVerboseStatusKey, PersistentDataType.BOOLEAN, !getLockVerboseStatus(player));
}
}
3 changes: 3 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ default-toggle-state: true
# Default Locking State: Controls if player's offhand are automatically locked by default.
default-lock-state: false

# Default warn player when locked that they can unlock it with a command.
default-lock-verbose-state: true

# DO NOT EDIT THE VERSION. Manual edits may corrupt or reset configuration files.
#
version: 3
4 changes: 3 additions & 1 deletion src/main/resources/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
###
prefix: "<dark_gray>[</dark_gray><gold>DynamicLights</gold><dark_gray>]</dark_gray>"

prevent-block-place: "<prefix> <gray>Light locking mode is currently enabled. You must sneak to place light sources from your Off Hand. This can be toggled with \"/dl lock\".</gray>"
prevent-block-place: "<prefix> <gray>Light locking mode is currently enabled. You must sneak to place light sources from your Off Hand. This can be toggled with \"/dl lock\". (Disable this message with \"/dl lockverbose\".)</gray>"
enable-lock: "<prefix> <gray>Enabled light lock mode.</gray>"
disable-lock: "<prefix> <gray>Disabled light lock mode.</gray>"
enable-lock-verbose: "<prefix> <gray>Enabled light lock mode warning message.</gray>"
disable-lock-verbose: "<prefix> <gray>Disabled light lock mode warning message.</gray>"
toggle-on: "<prefix> <gray>Light rendering enabled.</gray>"
toggle-off: "<prefix> <gray>Light rendering disabled.</gray>"
reload: "<prefix> <gray>Reloaded lights.yml configuration.</gray>"
Expand Down
8 changes: 5 additions & 3 deletions src/main/resources/locale/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
###
prefix: "<dark_gray>[</dark_gray><gold>DynamicLights</gold><dark_gray>]</dark_gray>"

prevent-block-place: "<prefix> <gray>Le mode de verrouillage des sources lumineuses est actuellement activé. Vous devez vous accroupir pour placer des sources lumineuses depuis votre main secondaire. Ce mode peut être désactivé avec la commande « /dl lock ».</gray>"
enable-lock: "<prefix> <gray>Mode de verrouillage lumineux activé.</gray>"
disable-lock: "<prefix> <gray>Mode de verrouillage lumineux désactivé.</gray>"
prevent-block-place: "<prefix> <gray>Le mode de verrouillage des sources lumineuses est actuellement activé. Vous devez vous accroupir pour placer des sources lumineuses depuis votre main secondaire. Ce mode peut être désactivé avec « /dl lock ». (Désactivez ce message avec « /dl lockverbose ».)</gray>"
enable-lock: "<prefix> <gray>Mode de verrouillage de la lumière activé.</gray>"
disable-lock: "<prefix> <gray>Mode de verrouillage de la lumière désactivé.</gray>"
enable-lock-verbose: "<prefix> <gray>Message d'avertissement du mode de verrouillage de la lumière activé.</gray>"
disable-lock-verbose: "<prefix> <gray>Message d'avertissement du mode de verrouillage de la lumière désactivé.</gray>"
toggle-on: "<prefix> <gray>Rendu de la lumière activé.</gray>"
toggle-off: "<prefix> <gray>Rendu de la lumière désactivé.</gray>"
reload: "<prefix> <gray>Configuration lights.yml rechargée.</gray>"
Expand Down