Skip to content
This repository was archived by the owner on Nov 20, 2025. It is now read-only.

Commit c459f52

Browse files
committed
Heavy optimize CPU and memory usages
Introduces reusable lists and maps for batch processing in Combat.java to reduce allocations, improves config value loading and reloads, and adds config reload support to GlowManager. Refactors CrystalManager to avoid unnecessary allocations. ChatUtil now short-circuits plain messages for performance. Removes unused throttling logic from SchedulerUtil. EntityDamageByEntityListener now caches references for efficiency.
1 parent 91c8a9b commit c459f52

7 files changed

Lines changed: 272 additions & 254 deletions

File tree

src/main/java/net/opmasterleo/combat/Combat.java

Lines changed: 217 additions & 196 deletions
Large diffs are not rendered by default.

src/main/java/net/opmasterleo/combat/listener/EntityDamageByEntityListener.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import net.opmasterleo.combat.Combat;
2727
import net.opmasterleo.combat.manager.SuperVanishManager;
2828
import net.opmasterleo.combat.util.SchedulerUtil;
29+
import net.opmasterleo.combat.util.WorldGuardUtil;
2930

3031
public final class EntityDamageByEntityListener implements PacketListener, Listener {
3132
private static final long ATTACK_TIMEOUT = 5000;
@@ -35,12 +36,18 @@ public final class EntityDamageByEntityListener implements PacketListener, Liste
3536
private final Map<UUID, Long> attackTimestamps = new ConcurrentHashMap<>();
3637
private final Combat combatInstance = Combat.getInstance();
3738
private boolean initialized = false;
39+
private NewbieProtectionListener protectionListener;
40+
private WorldGuardUtil worldGuardUtil;
41+
private SuperVanishManager vanishManager;
3842

3943
public EntityDamageByEntityListener() {
4044
}
4145

4246
public void initialize() {
4347
if (initialized) return;
48+
protectionListener = combatInstance.getNewbieProtectionListener();
49+
worldGuardUtil = combatInstance.getWorldGuardUtil();
50+
vanishManager = combatInstance.getSuperVanishManager();
4451

4552
combatInstance.getServer().getPluginManager().registerEvents(this, combatInstance);
4653
if (combatInstance.isPacketEventsAvailable()) {
@@ -113,19 +120,17 @@ private boolean isCreativeOrSpectator(Player player) {
113120
}
114121

115122
private boolean isProtectedInteraction(Player attacker, Player victim) {
116-
NewbieProtectionListener protectionListener = combatInstance.getNewbieProtectionListener();
117123
if (protectionListener != null) {
118124
boolean attackerProtected = protectionListener.isActuallyProtected(attacker);
119125
boolean victimProtected = protectionListener.isActuallyProtected(victim);
120126
if (attackerProtected != victimProtected) return true;
121127
}
122128

123-
if (combatInstance.getWorldGuardUtil() != null && combatInstance.getWorldGuardUtil().isPvpDenied(victim.getLocation())) {
129+
if (worldGuardUtil != null && worldGuardUtil.isPvpDenied(victim.getLocation())) {
124130
return true;
125131
}
126132

127-
SuperVanishManager vanish = combatInstance.getSuperVanishManager();
128-
return vanish != null && (vanish.isVanished(attacker) || vanish.isVanished(victim));
133+
return vanishManager != null && (vanishManager.isVanished(attacker) || vanishManager.isVanished(victim));
129134
}
130135

131136
private boolean isSelfAttack(Player attacker, Player victim) {

src/main/java/net/opmasterleo/combat/manager/CrystalManager.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,16 @@ public void setPlacer(Entity crystal, Player placer) {
6161
UUID crystalId = crystal.getUniqueId();
6262
UUID placerId = placer.getUniqueId();
6363

64-
crystalData.computeIfAbsent(crystalId, k -> new CrystalData(placerId, crystal.getWorld().getName()));
65-
playerCrystals.computeIfAbsent(placerId, k -> ConcurrentHashMap.newKeySet()).add(crystalId);
64+
crystalData.putIfAbsent(crystalId, new CrystalData(placerId, crystal.getWorld().getName()));
65+
Set<UUID> crystals = playerCrystals.get(placerId);
66+
if (crystals == null) {
67+
crystals = ConcurrentHashMap.newKeySet();
68+
Set<UUID> existing = playerCrystals.putIfAbsent(placerId, crystals);
69+
if (existing != null) {
70+
crystals = existing;
71+
}
72+
}
73+
crystals.add(crystalId);
6674

6775
if (System.currentTimeMillis() - lastCleanup > CLEANUP_INTERVAL) {
6876
plugin.getCombatWorkerPool().execute(this::cleanupExpiredEntries);

src/main/java/net/opmasterleo/combat/manager/GlowManager.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class GlowManager {
3131
private static final long PACKET_THROTTLE_MS = 50;
3232
private static final int CLEANUP_THRESHOLD = 100;
3333
private volatile boolean enabled = true;
34+
private volatile boolean glowingConfigEnabled = true;
3435

3536
private static class GlowState {
3637
final boolean isGlowing;
@@ -44,6 +45,7 @@ private static class GlowState {
4445

4546
public void initialize(Combat plugin) {
4647
this.plugin = plugin;
48+
this.glowingConfigEnabled = plugin.getConfig().getBoolean("General.CombatTagGlowing", false);
4749
schedulePeriodicCleanup();
4850
schedulePeriodicSync();
4951
}
@@ -52,6 +54,10 @@ public void setEnabled(boolean enabled) {
5254
this.enabled = enabled;
5355
}
5456

57+
public void reloadConfig() {
58+
this.glowingConfigEnabled = plugin.getConfig().getBoolean("General.CombatTagGlowing", false);
59+
}
60+
5561
private void schedulePeriodicCleanup() {
5662
SchedulerUtil.runTaskTimerAsync(plugin, () -> {
5763
long now = System.currentTimeMillis();
@@ -83,7 +89,7 @@ private void schedulePeriodicCleanup() {
8389
private void schedulePeriodicSync() {
8490
SchedulerUtil.runTaskTimerAsync(plugin, () -> {
8591
try {
86-
if (!enabled || !plugin.getConfig().getBoolean("General.CombatTagGlowing", false)) {
92+
if (!enabled || !glowingConfigEnabled) {
8793
return;
8894
}
8995
List<Player> playersToSync = new ArrayList<>();
@@ -148,7 +154,7 @@ public void setGlowing(Player player, boolean glowing, UUID opponentId) {
148154
return;
149155
}
150156

151-
if (glowing && (!enabled || !plugin.getConfig().getBoolean("General.CombatTagGlowing", false))) {
157+
if (glowing && (!enabled || !glowingConfigEnabled)) {
152158
glowingPlayers.remove(playerId);
153159
removeGlowEffect(player);
154160
return;
@@ -165,7 +171,7 @@ public void setGlowing(Player player, boolean glowing, UUID opponentId) {
165171

166172
public boolean syncWithCombat(Player player) {
167173
if (player == null) return false;
168-
if (!enabled || !plugin.getConfig().getBoolean("General.CombatTagGlowing", false)) {
174+
if (!enabled || !glowingConfigEnabled) {
169175
GlowState current = glowingPlayers.get(player.getUniqueId());
170176
if (current != null && current.isGlowing) {
171177
setGlowing(player, false, null);
@@ -238,7 +244,7 @@ public void cleanup() {
238244

239245
private void applyGlowEffect(Player player, UUID opponentId) {
240246
if (player == null) return;
241-
if (!enabled || !plugin.getConfig().getBoolean("General.CombatTagGlowing", false)) return;
247+
if (!enabled || !glowingConfigEnabled) return;
242248

243249
try {
244250
setGlowingWithPacketEvents(player, true, opponentId);
@@ -314,7 +320,7 @@ private void removeGlowEffect(Player player) {
314320

315321
private void setGlowingWithPacketEvents(Player player, boolean glowing, UUID opponentId) {
316322
if (player == null) return;
317-
if (!enabled || !plugin.getConfig().getBoolean("General.CombatTagGlowing", false)) {
323+
if (!enabled || !glowingConfigEnabled) {
318324
if (glowing) return;
319325
}
320326

src/main/java/net/opmasterleo/combat/util/ChatUtil.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package net.opmasterleo.combat.util;
22

3+
import java.util.regex.Matcher;
4+
import java.util.regex.Pattern;
5+
36
import net.kyori.adventure.text.Component;
47
import net.kyori.adventure.text.TextComponent;
58
import net.kyori.adventure.text.format.NamedTextColor;
@@ -9,9 +12,6 @@
912
import net.kyori.adventure.text.minimessage.tag.standard.StandardTags;
1013
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
1114

12-
import java.util.regex.Matcher;
13-
import java.util.regex.Pattern;
14-
1515
public class ChatUtil {
1616
private static final Pattern HEX_COLOR_PATTERN = Pattern.compile("&#([A-Fa-f0-9]{6})");
1717

@@ -29,6 +29,10 @@ public static Component parse(String message) {
2929
return Component.empty();
3030
}
3131

32+
if (message.indexOf('&') == -1 && message.indexOf('<') == -1 && message.indexOf('§') == -1) {
33+
return Component.text(message);
34+
}
35+
3236
if (message.indexOf('<') != -1 && message.indexOf('>') != -1) {
3337
try {
3438
return MINI_MESSAGE.deserialize(message);
@@ -37,6 +41,14 @@ public static Component parse(String message) {
3741
}
3842

3943
String processed = message.replace('&', '§');
44+
if (processed.indexOf('#') == -1) {
45+
try {
46+
return LegacyComponentSerializer.legacySection().deserialize(processed);
47+
} catch (Exception e) {
48+
return Component.text(message).color(NamedTextColor.WHITE);
49+
}
50+
}
51+
4052
Matcher matcher = HEX_COLOR_PATTERN.matcher(processed);
4153
if (!matcher.find()) {
4254
try {
@@ -45,8 +57,9 @@ public static Component parse(String message) {
4557
return Component.text(message).color(NamedTextColor.WHITE);
4658
}
4759
}
60+
4861
matcher.reset();
49-
StringBuilder sb = new StringBuilder(processed.length() + 32);
62+
StringBuilder sb = new StringBuilder(processed.length() + (matcher.groupCount() * 14));
5063
int lastEnd = 0;
5164
while (matcher.find()) {
5265
sb.append(processed, lastEnd, matcher.start());

src/main/java/net/opmasterleo/combat/util/ConfigUtil.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.opmasterleo.combat.util;
22

3+
import java.io.BufferedReader;
34
import java.io.File;
45
import java.io.FileInputStream;
56
import java.io.FileOutputStream;
@@ -554,15 +555,15 @@ private static String extractHeader(File configFile) {
554555

555556
private static String readSansHeader(File configFile) {
556557
if (configFile == null || !configFile.exists()) return null;
557-
try (FileInputStream fis = new FileInputStream(configFile)) {
558-
byte[] bytes = fis.readAllBytes();
559-
String content = new String(bytes, StandardCharsets.UTF_8);
560-
String[] lines = content.split("\r?\n", -1);
561-
StringBuilder body = new StringBuilder();
558+
try (BufferedReader reader = new BufferedReader(
559+
new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8))) {
560+
StringBuilder body = new StringBuilder(1024);
561+
String line;
562562
boolean started = false;
563-
for (String line : lines) {
563+
while ((line = reader.readLine()) != null) {
564564
if (!started) {
565-
if (line.trim().startsWith("#") || line.trim().isEmpty()) {
565+
String trimmed = line.trim();
566+
if (trimmed.isEmpty() || trimmed.startsWith("#")) {
566567
continue;
567568
}
568569
started = true;

src/main/java/net/opmasterleo/combat/util/SchedulerUtil.java

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -265,32 +265,6 @@ private static String getRegionKey(Location location) {
265265
return location.getWorld().getName() + ":" + (location.getBlockX() >> 9) + ":" + (location.getBlockZ() >> 9);
266266
}
267267

268-
private static boolean shouldThrottleRegion(Location location, long minInterval) {
269-
if (location == null || minInterval <= 0) {
270-
return false;
271-
}
272-
return false;
273-
}
274-
275-
private static boolean shouldThrottleEntity(Entity entity, long minInterval) {
276-
if (entity == null || minInterval <= 0) {
277-
return false;
278-
}
279-
return false;
280-
}
281-
282-
private static void incrementRegionCounter(Location location) {
283-
if (location != null) {
284-
location.getWorld();
285-
}
286-
}
287-
288-
private static void incrementEntityCounter(Entity entity) {
289-
if (entity != null) {
290-
entity.getType();
291-
}
292-
}
293-
294268
private static boolean canRunAsync() {
295269
return activeAsyncTasks.get() < MAX_CONCURRENT_ASYNC_TASKS;
296270
}
@@ -499,11 +473,6 @@ public static void runEntityTaskTimer(Plugin plugin, Entity entity, Runnable tas
499473
public static void runEntityTaskTimer(Plugin plugin, Entity entity, Runnable task, long delay, long period, long minInterval) {
500474
if (shouldSkip(plugin) || entity == null || !entity.isValid()) return;
501475

502-
if (minInterval > 0 && shouldThrottleEntity(entity, minInterval)) {
503-
return;
504-
}
505-
506-
incrementEntityCounter(entity);
507476
Runnable wrapped = wrapTask(task, plugin, "entity");
508477

509478
if (IS_FOLIA || IS_CANVAS) {
@@ -550,11 +519,6 @@ public static void runRegionTaskTimer(Plugin plugin, Location location, Runnable
550519
public static void runRegionTaskTimer(Plugin plugin, Location location, Runnable task, long delay, long period, long minInterval) {
551520
if (shouldSkip(plugin)) return;
552521

553-
if (minInterval > 0 && shouldThrottleRegion(location, minInterval)) {
554-
return;
555-
}
556-
557-
incrementRegionCounter(location);
558522
Runnable wrapped = wrapTask(task, plugin, "region");
559523

560524
if (IS_FOLIA || IS_CANVAS) {

0 commit comments

Comments
 (0)