@@ -3,19 +3,84 @@ package li.angu.challengeplugin.listeners
3
3
import li.angu.challengeplugin.ChallengePluginPlugin
4
4
import org.bukkit.event.EventHandler
5
5
import org.bukkit.event.Listener
6
- import org.bukkit.event.player.PlayerExpChangeEvent
7
6
import org.bukkit.event.player.PlayerLevelChangeEvent
8
7
import org.bukkit.event.player.PlayerJoinEvent
9
8
import org.bukkit.event.player.PlayerChangedWorldEvent
9
+ import org.bukkit.Bukkit
10
+ import org.bukkit.Location
11
+ import org.bukkit.WorldBorder
12
+ import org.bukkit.entity.Player
13
+ import org.bukkit.scheduler.BukkitTask
14
+ import java.util.UUID
15
+ import java.util.concurrent.ConcurrentHashMap
10
16
11
17
/* *
12
18
* This listener manages the world border adjustment based on player experience level
13
19
* when the Level WorldBorder setting is enabled.
20
+ *
21
+ * This implementation simulates per-player borders by repeatedly updating the world border
22
+ * for each player, making it appear as if they have individual borders.
14
23
*/
15
24
class ExperienceBorderListener (private val plugin : ChallengePluginPlugin ) : Listener {
16
25
26
+ // Border update task
27
+ private var borderUpdateTask: BukkitTask ? = null
28
+
17
29
init {
18
30
plugin.server.pluginManager.registerEvents(this , plugin)
31
+
32
+ // Start a repeating task to update borders for all players
33
+ // We only need to update occasionally since we're storing per-player borders
34
+ borderUpdateTask = Bukkit .getScheduler().runTaskTimer(plugin, Runnable {
35
+ updateAllPlayerBorders()
36
+ }, 10L , 20L ) // Update every 20 ticks (1 second)
37
+ }
38
+
39
+ /* *
40
+ * Update borders for all online players in challenges
41
+ */
42
+ private fun updateAllPlayerBorders () {
43
+ Bukkit .getOnlinePlayers().forEach { player ->
44
+ val challenge = plugin.challengeManager.getPlayerChallenge(player) ? : return @forEach
45
+
46
+ if (! challenge.settings.levelWorldBorder) return @forEach
47
+
48
+ updatePlayerBorder(player, challenge.settings.borderSize, player.world.spawnLocation)
49
+ }
50
+ }
51
+
52
+ // Store a world border for each world to avoid recreating it
53
+ private val worldBorders = mutableMapOf<String , WorldBorder >()
54
+
55
+ /* *
56
+ * Update a single player's border
57
+ */
58
+ private fun updatePlayerBorder (player : Player , size : Double , center : Location ) {
59
+ try {
60
+ val world = player.world
61
+
62
+ // Create a custom WorldBorder object for each world if it doesn't exist
63
+ val worldBorder = worldBorders.computeIfAbsent(world.name) {
64
+ // Create a new WorldBorder directly
65
+ val border = Bukkit .createWorldBorder()
66
+ // Set this to be very far away and very large by default
67
+ border.center = Location (world, 0.0 , 0.0 , 0.0 )
68
+ border.size = 60000000.0 // Nearly unlimited
69
+ border
70
+ }
71
+
72
+ // Only update if necessary
73
+ if (worldBorder.size != size || worldBorder.center != center) {
74
+ worldBorder.size = size
75
+ worldBorder.center = center
76
+ }
77
+
78
+ // Send the border to the player without changing the world's actual border
79
+ player.worldBorder = worldBorder
80
+ } catch (e: Exception ) {
81
+ // Log any errors but don't crash the plugin
82
+ plugin.logger.warning(" Error updating border for player ${player.name} : ${e.message} " )
83
+ }
19
84
}
20
85
21
86
/* *
@@ -25,90 +90,73 @@ class ExperienceBorderListener(private val plugin: ChallengePluginPlugin) : List
25
90
fun onPlayerLevelUp (event : PlayerLevelChangeEvent ) {
26
91
val player = event.player
27
92
val challenge = plugin.challengeManager.getPlayerChallenge(player) ? : return
28
-
93
+
29
94
// Check if the level world border setting is enabled for this challenge
30
95
if (! challenge.settings.levelWorldBorder) return
31
-
96
+
32
97
// Only apply when level increases (not when it decreases)
33
98
if (event.newLevel <= event.oldLevel) return
34
-
35
- // Get the player's current world
36
- val world = player.world
37
-
38
- // Get current border size and add 2
39
- val currentSize = world.worldBorder.size
40
- val newSize = currentSize + 2.0
41
-
42
- // Set the border
43
- world.worldBorder.size = newSize
44
-
45
- // Send a message to players in the challenge
46
- val message = plugin.languageManager.getMessage(
47
- " challenge.border_expanded" ,
48
- player,
49
- " level" to event.newLevel.toString(),
50
- " size" to newSize.toInt().toString()
51
- )
52
-
99
+
100
+ // Increase border by 1 block on each level up (+2 blocks total diameter)
101
+ challenge.settings.borderSize + = 2.0
102
+
103
+ // Save all challenges to persist the border size
104
+ plugin.challengeManager.saveActiveChallenges()
105
+
106
+ // Update borders for all players in this challenge immediately
53
107
challenge.players.forEach { playerId ->
54
- plugin.server.getPlayer(playerId)?.sendMessage(message)
108
+ plugin.server.getPlayer(playerId)?.let { challengePlayer ->
109
+ updatePlayerBorder(challengePlayer, challenge.settings.borderSize, challengePlayer.world.spawnLocation)
110
+ }
55
111
}
56
112
}
57
-
113
+
58
114
/* *
59
- * When a player joins, don't modify the border
60
- * Border only expands when players level up
115
+ * When a player joins, initialize their border
61
116
*/
62
117
@EventHandler
63
118
fun onPlayerJoin (event : PlayerJoinEvent ) {
64
- // No longer adjusting border on join - only increases on level up
119
+ val player = event.player
120
+ val challenge = plugin.challengeManager.getPlayerChallenge(player) ? : return
121
+
122
+ if (! challenge.settings.levelWorldBorder) return
123
+
124
+ // Immediately update the border for the player using the challenge's saved border size
125
+ updatePlayerBorder(player, challenge.settings.borderSize, player.world.spawnLocation)
65
126
}
66
-
127
+
67
128
/* *
68
- * When a player changes worlds, initialize the border if needed
129
+ * When a player changes worlds, update their border center
69
130
*/
70
131
@EventHandler
71
132
fun onPlayerChangeWorld (event : PlayerChangedWorldEvent ) {
72
133
val player = event.player
73
134
val challenge = plugin.challengeManager.getPlayerChallenge(player) ? : return
74
-
135
+
75
136
if (! challenge.settings.levelWorldBorder) return
76
-
77
- // Only care about challenge worlds
78
- if (event.player.world.name == challenge.worldName ||
79
- event.player.world.name == " ${challenge.worldName} _nether" ||
80
- event.player.world.name == " ${challenge.worldName} _the_end" ) {
81
-
82
- // Initialize the border in the new world if it's too small
83
- val world = event.player.world
84
- if (world.worldBorder.size < 3.0 ) {
85
- world.worldBorder.size = 3.0 // Initialize with minimum size
86
- }
87
- }
137
+
138
+ // Immediately update the border for the player in the new world
139
+ updatePlayerBorder(player, challenge.settings.borderSize, player.world.spawnLocation)
88
140
}
89
-
141
+
90
142
/* *
91
- * Initialize world border size for all worlds in a challenge
92
- * This method can be called when a challenge is created to set initial border
143
+ * Initialize world borders for players in a challenge
144
+ * This method should be called when a challenge is created or reset
93
145
*/
94
- private fun initializeWorldBordersForChallenge (challenge : li.angu.challengeplugin.models.Challenge ) {
146
+ fun initializeWorldBordersForPlayers (challenge : li.angu.challengeplugin.models.Challenge ) {
95
147
if (! challenge.settings.levelWorldBorder) return
96
148
97
- val initialSize = 3.0 // Starting with 3x3 border
98
-
99
- // Initialize main world
100
- plugin.server.getWorld(challenge.worldName)?.let { world ->
101
- world.worldBorder.size = initialSize
102
- }
103
-
104
- // Initialize nether
105
- challenge.getNetherWorld()?.let { world ->
106
- world.worldBorder.size = initialSize
107
- }
149
+ // Initialize with the challenge's saved border size or the default
150
+ // No need to calculate, as the border size is now a persistent property
108
151
109
- // Initialize end
110
- challenge.getEndWorld()?.let { world ->
111
- world.worldBorder.size = initialSize
112
- }
152
+ // The borders will be updated by the repeating task
153
+ }
154
+
155
+ /* *
156
+ * Clean up tasks when plugin is disabled
157
+ */
158
+ fun cleanup () {
159
+ borderUpdateTask?.cancel()
160
+ borderUpdateTask = null
113
161
}
114
- }
162
+ }
0 commit comments