getActiveEntities() {
+ return List.copyOf(BLIGHTED_ENTITIES.values());
+ }
+
+ /**
+ * Removes attachment owner tracking entry by entity UUID.
+ *
+ * @param entityId target attachment entity unique identifier
+ */
+ public static void removeAttachmentOwner(UUID entityId) {
+ if (entityId == null) return;
+ ATTACHMENT_OWNERS.remove(entityId);
+ }
+
+ /**
+ * Removes direct blighted entity tracking entry by entity UUID.
+ *
+ * @param entityId target entity unique identifier
+ */
+ public static void removeDirectBlightedEntity(UUID entityId) {
+ if (entityId == null) return;
+ BLIGHTED_ENTITIES.remove(entityId);
+ }
+
+ /**
+ * Rehydrates blighted entities and attachment entities stored in persistent data when chunk loads.
+ *
+ * @param chunk loaded chunk to rehydrate
+ */
+ public static void rehydrateChunk(Chunk chunk) {
+ if (chunk == null || !chunk.isLoaded()) {
+ return;
+ }
+ Entity[] entities = chunk.getEntities();
+
+ // Pass 1: rehydrate main blighted entities.
+ for (Entity entity : entities) {
+ if (!(entity instanceof LivingEntity living)) continue;
+ if (!living.getScoreboardTags().contains(FAST_PASS_TAG)) continue;
+
+ PersistentDataContainer persistentDataContainer = living.getPersistentDataContainer();
+ if (!persistentDataContainer.has(ENTITY_ID_KEY, PersistentDataType.STRING)) continue;
+
+ BlightedEntity existing = BLIGHTED_ENTITIES.get(living.getUniqueId());
+ if (existing != null) {
+ if (existing.getEntity() != living) {
+ existing.attachToExisting(living);
+ }
+ continue;
+ }
+
+ String entityId = persistentDataContainer.get(ENTITY_ID_KEY, PersistentDataType.STRING);
+ BlightedEntity prototype = EntitiesRegistry.get(entityId);
+ if (prototype == null) continue;
+
+ prototype.clone().attachToExisting(living);
+ }
+
+ // Pass 2: re-register attachment entities carrying ATTACHMENT_OWNER_KEY.
+ for (Entity entity : entities) {
+ if (!entity.getScoreboardTags().contains(FAST_PASS_TAG)) continue;
+
+ PersistentDataContainer persistentDataContainer = entity.getPersistentDataContainer();
+ if (!persistentDataContainer.has(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING)) continue;
+
+ String ownerUuidString = persistentDataContainer.get(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING);
+ String roleString = persistentDataContainer.get(ATTACHMENT_ROLE_KEY, PersistentDataType.STRING);
+ if (ownerUuidString == null || roleString == null) continue;
+
+ UUID ownerUuid;
+ try {
+ ownerUuid = UUID.fromString(ownerUuidString);
+ } catch (IllegalArgumentException _) {
+ continue;
+ }
+
+ BlightedEntity owner = BLIGHTED_ENTITIES.get(ownerUuid);
+ if (owner == null) continue;
+
+ AttachmentRole role;
+ try {
+ role = AttachmentRole.valueOf(roleString);
+ } catch (IllegalArgumentException _) {
+ role = AttachmentRole.SUBORDINATE;
+ }
+
+ Double offsetX = persistentDataContainer.get(ATTACHMENT_OFFSET_X_KEY, PersistentDataType.DOUBLE);
+ Double offsetY = persistentDataContainer.get(ATTACHMENT_OFFSET_Y_KEY, PersistentDataType.DOUBLE);
+ Double offsetZ = persistentDataContainer.get(ATTACHMENT_OFFSET_Z_KEY, PersistentDataType.DOUBLE);
+ Vector offset = new Vector(
+ offsetX != null ? offsetX : 0.0,
+ offsetY != null ? offsetY : 0.0,
+ offsetZ != null ? offsetZ : 0.0
+ );
+
+ Byte yawByte = persistentDataContainer.get(ATTACHMENT_SYNC_YAW_KEY, PersistentDataType.BYTE);
+ Byte pitchByte = persistentDataContainer.get(ATTACHMENT_SYNC_PITCH_KEY, PersistentDataType.BYTE);
+ boolean syncYaw = yawByte == null || yawByte == 1;
+ boolean syncPitch = pitchByte != null && pitchByte == 1;
+
+ owner.attachments.removeIf(a -> a.entity() != null && a.entity().getUniqueId().equals(entity.getUniqueId()));
+ owner.attachments.add(new EntityAttachment(entity, role, offset, syncYaw, syncPitch));
+ registerAttachment(entity, owner);
+ }
+
+ // Pass 3: Purge orphan attachments whose owner entity no longer exists.
+ Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(), () -> {
+ if (!chunk.isLoaded()) return;
+ for (Entity entity : chunk.getEntities()) {
+ if (!entity.getScoreboardTags().contains(FAST_PASS_TAG)) continue;
+ PersistentDataContainer persistentDataContainer = entity.getPersistentDataContainer();
+ if (!persistentDataContainer.has(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING)) continue;
+
+ String ownerUuidString = persistentDataContainer.get(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING);
+ if (ownerUuidString == null) continue;
+
+ try {
+ UUID ownerUuid = UUID.fromString(ownerUuidString);
+ BlightedEntity owner = BLIGHTED_ENTITIES.get(ownerUuid);
+ if (owner == null || owner.getEntity() == null || !owner.getEntity().isValid()) {
+ entity.remove();
+ ATTACHMENT_OWNERS.remove(entity.getUniqueId());
+ }
+ } catch (IllegalArgumentException _) {
+ entity.remove();
+ }
+ }
+ }, 3L);
+ }
+}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java
index 2b20f476..a4335e51 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java
@@ -1,29 +1,49 @@
package fr.moussax.blightedSMP.engine.entities;
import fr.moussax.blightedSMP.BlightedSMP;
+import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.scheduler.BukkitTask;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
/**
- * Manages scheduler tasks bound to the lifecycle of an {@link BlightedEntity}.
+ * Manages scheduler tasks bound to the lifecycle of a {@link BlightedEntity}.
*
- * Allows entities to register delayed or repeating {@link BukkitRunnable} tasks that
- * are automatically scheduled on initialization and canceled on destruction.
- * Tasks are executed through the {@link BlightedSMP} plugin scheduler and can be
- * rescheduled as needed during the entity’s lifetime.
+ * Allows entities to register delayed or repeating tasks that are automatically
+ * scheduled on initialization and canceled on destruction.
*/
public final class LifecycleTaskManager {
+ private List tasks;
+
/**
- * Holds all registered scheduled tasks for the associated entity.
+ * Adds a repeating task using a {@link Runnable} action.
+ *
+ * @param action task action
+ * @param delayTicks initial delay in ticks
+ * @param periodTicks execution interval in ticks
*/
- private List tasks;
+ public void addRepeatingTask(Runnable action, long delayTicks, long periodTicks) {
+ ensureList();
+ tasks.add(new ScheduledTask(action, null, delayTicks, periodTicks, true));
+ }
+
+ /**
+ * Adds a delayed task using a {@link Runnable} action.
+ *
+ * @param action task action
+ * @param delayTicks delay in ticks
+ */
+ public void addDelayedTask(Runnable action, long delayTicks) {
+ ensureList();
+ tasks.add(new ScheduledTask(action, null, delayTicks, 0L, false));
+ }
/**
- * Adds a repeating task that executes periodically for the entity lifecycle.
+ * Adds a repeating task using a {@link BukkitRunnable} supplier (for backwards compatibility).
*
* @param factory supplier creating a new {@link BukkitRunnable} instance
* @param delayTicks initial delay before the first execution, in ticks
@@ -31,23 +51,22 @@ public final class LifecycleTaskManager {
*/
public void addRepeatingTask(Supplier factory, long delayTicks, long periodTicks) {
ensureList();
- tasks.add(new ScheduledTask(factory, delayTicks, periodTicks, true));
+ tasks.add(new ScheduledTask(null, factory, delayTicks, periodTicks, true));
}
/**
- * Adds a delayed one-time task that runs once after the given delay.
+ * Adds a delayed task using a {@link BukkitRunnable} supplier (for backwards compatibility).
*
* @param factory supplier creating a new {@link BukkitRunnable} instance
* @param delayTicks delay before execution, in ticks
*/
public void addDelayedTask(Supplier factory, long delayTicks) {
ensureList();
- tasks.add(new ScheduledTask(factory, delayTicks, 0L, false));
+ tasks.add(new ScheduledTask(null, factory, delayTicks, 0L, false));
}
/**
- * Schedules all registered tasks. This is typically invoked
- * during the entity’s runtime initialization phase.
+ * Schedules all registered tasks.
*/
public void scheduleAll() {
if (tasks == null) return;
@@ -58,7 +77,6 @@ public void scheduleAll() {
/**
* Schedules only the most recently added task.
- * Useful for adding new runtime behaviors dynamically.
*/
public void scheduleLast() {
if (tasks == null || tasks.isEmpty()) return;
@@ -66,8 +84,7 @@ public void scheduleLast() {
}
/**
- * Cancels all currently running scheduled tasks associated with the entity.
- * This should be invoked during entity destruction or killing.
+ * Cancels all currently running tasks associated with this manager.
*/
public void cancelAll() {
if (tasks == null) return;
@@ -85,21 +102,19 @@ private void ensureList() {
private void onTaskComplete(ScheduledTask task) {
if (tasks == null) return;
tasks.remove(task);
- task.current = null;
}
- /**
- * Represents a scheduled Bukkit task bound to an entity’s lifecycle.
- * Handles its own scheduling, cancellation, and re-initialization logic.
- */
private static final class ScheduledTask {
+ private final Runnable action;
private final Supplier factory;
private final long delayTicks;
private final long periodTicks;
private final boolean repeating;
- private BukkitRunnable current;
+ private BukkitTask currentTask;
+ private BukkitRunnable currentRunnable;
- private ScheduledTask(Supplier factory, long delayTicks, long periodTicks, boolean repeating) {
+ private ScheduledTask(Runnable action, Supplier factory, long delayTicks, long periodTicks, boolean repeating) {
+ this.action = action;
this.factory = factory;
this.delayTicks = delayTicks;
this.periodTicks = periodTicks;
@@ -110,35 +125,55 @@ private void schedule(LifecycleTaskManager manager) {
cancel();
if (repeating) {
- current = factory.get();
- current.runTaskTimer(BlightedSMP.getInstance(), delayTicks, periodTicks);
+ if (action != null) {
+ currentTask = Bukkit.getScheduler().runTaskTimer(BlightedSMP.getInstance(), action, delayTicks, periodTicks);
+ } else if (factory != null) {
+ currentRunnable = factory.get();
+ currentTask = currentRunnable.runTaskTimer(BlightedSMP.getInstance(), delayTicks, periodTicks);
+ }
} else {
- current = new BukkitRunnable() {
- private final BukkitRunnable inner = factory.get();
-
- @Override
- public void run() {
+ if (action != null) {
+ currentTask = Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(), () -> {
try {
- if (inner != null) inner.run();
+ action.run();
} finally {
- // Ensure this is removed from the list even if the logic crashes
manager.onTaskComplete(ScheduledTask.this);
}
- }
- };
- current.runTaskLater(BlightedSMP.getInstance(), delayTicks);
+ }, delayTicks);
+ } else if (factory != null) {
+ currentRunnable = new BukkitRunnable() {
+ private final BukkitRunnable inner = factory.get();
+
+ @Override
+ public void run() {
+ try {
+ if (inner != null) inner.run();
+ } finally {
+ manager.onTaskComplete(ScheduledTask.this);
+ }
+ }
+ };
+ currentTask = currentRunnable.runTaskLater(BlightedSMP.getInstance(), delayTicks);
+ }
}
}
private void cancel() {
- if (current != null) {
+ if (currentTask != null) {
+ try {
+ currentTask.cancel();
+ } catch (Exception _) {
+ }
+ currentTask = null;
+ }
+ if (currentRunnable != null) {
try {
- if (!current.isCancelled()) {
- current.cancel();
+ if (!currentRunnable.isCancelled()) {
+ currentRunnable.cancel();
}
- } catch (IllegalStateException ignored) {
+ } catch (Exception _) {
}
- current = null;
+ currentRunnable = null;
}
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
index fd8e9934..0ea11df4 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
@@ -2,96 +2,93 @@
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.engine.entities.BlightedEntity;
+import fr.moussax.blightedSMP.engine.entities.EntityManager;
import fr.moussax.blightedSMP.engine.entities.attachment.AttachmentRole;
import fr.moussax.blightedSMP.engine.entities.attachment.EntityAttachment;
import fr.moussax.blightedSMP.engine.entities.defense.EntityImmunity;
-import fr.moussax.blightedSMP.engine.entities.registry.EntitiesRegistry;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Sound;
-import org.bukkit.entity.*;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-import org.bukkit.event.entity.EntityDamageEvent;
-import org.bukkit.event.entity.EntityDeathEvent;
-import org.bukkit.event.entity.EntityPotionEffectEvent;
-import org.bukkit.event.entity.EntityRegainHealthEvent;
+import org.bukkit.event.entity.*;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.util.Vector;
-import java.util.*;
+import java.util.Collection;
+import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_OFFSET_X_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_OFFSET_Y_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_OFFSET_Z_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_OWNER_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_ROLE_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_SYNC_PITCH_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ATTACHMENT_SYNC_YAW_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.ENTITY_ID_KEY;
-import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.FAST_PASS_TAG;
+import static fr.moussax.blightedSMP.engine.entities.BlightedEntity.*;
+/**
+ * Event listener handling damage, potion effects, health updates, death, and chunk loading
+ * for {@link BlightedEntity} instances and delegating runtime entity tracking to {@link EntityManager}.
+ */
public final class BlightedEntitiesListener implements Listener {
- private static final Map BLIGHTED_ENTITIES = new ConcurrentHashMap<>();
- private static final Map ATTACHMENT_OWNERS = new ConcurrentHashMap<>();
private final Set processingDamageIds = ConcurrentHashMap.newKeySet();
- private static final long ORPHAN_SWEEP_PERIOD_TICKS = 100L; // 5s
-
public BlightedEntitiesListener() {
- Bukkit.getScheduler().runTaskTimer(
- BlightedSMP.getInstance(), BlightedEntitiesListener::sweepOrphanedEntities,
- ORPHAN_SWEEP_PERIOD_TICKS, ORPHAN_SWEEP_PERIOD_TICKS
- );
- }
-
- private static void sweepOrphanedEntities() {
- for (BlightedEntity blighted : List.copyOf(BLIGHTED_ENTITIES.values())) {
- LivingEntity entity = blighted.getEntity();
- if (entity == null || entity.isDead() || !entity.isValid()) {
- if (entity != null) {
- BLIGHTED_ENTITIES.remove(entity.getUniqueId(), blighted);
- } else {
- BLIGHTED_ENTITIES.values().remove(blighted);
- }
- blighted.cleanup();
- }
- }
+ EntityManager.initialize();
}
+ /**
+ * Delegates entity registration to {@link EntityManager#registerEntity(LivingEntity, BlightedEntity)}.
+ *
+ * @param entity living entity to track
+ * @param blighted blighted entity wrapper instance
+ */
public static void registerEntity(LivingEntity entity, BlightedEntity blighted) {
- if (entity == null || blighted == null) return;
- BLIGHTED_ENTITIES.put(entity.getUniqueId(), blighted);
+ EntityManager.registerEntity(entity, blighted);
}
+ /**
+ * Delegates entity unregistration to {@link EntityManager#unregisterEntity(LivingEntity)}.
+ *
+ * @param entity living entity to stop tracking
+ */
public static void unregisterEntity(LivingEntity entity) {
- if (entity == null) return;
- BLIGHTED_ENTITIES.remove(entity.getUniqueId());
+ EntityManager.unregisterEntity(entity);
}
+ /**
+ * Delegates attachment registration to {@link EntityManager#registerAttachment(Entity, BlightedEntity)}.
+ *
+ * @param attachment attachment entity
+ * @param owner owning blighted entity wrapper
+ */
public static void registerAttachment(Entity attachment, BlightedEntity owner) {
- if (attachment == null || owner == null) return;
- ATTACHMENT_OWNERS.put(attachment.getUniqueId(), owner);
+ EntityManager.registerAttachment(attachment, owner);
}
+ /**
+ * Delegates attachment unregistration to {@link EntityManager#unregisterAttachment(Entity)}.
+ *
+ * @param attachment attachment entity to unregister
+ */
public static void unregisterAttachment(Entity attachment) {
- if (attachment == null) return;
- ATTACHMENT_OWNERS.remove(attachment.getUniqueId());
+ EntityManager.unregisterAttachment(attachment);
}
+ /**
+ * Delegates entity lookup to {@link EntityManager#getBlightedEntity(Entity)}.
+ *
+ * @param entity target entity
+ * @return blighted entity wrapper, or {@code null} if untracked
+ */
public static BlightedEntity getBlightedEntity(Entity entity) {
- if (entity == null) return null;
- UUID id = entity.getUniqueId();
- BlightedEntity blighted = BLIGHTED_ENTITIES.get(id);
- return blighted != null ? blighted : ATTACHMENT_OWNERS.get(id);
+ return EntityManager.getBlightedEntity(entity);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@@ -108,12 +105,12 @@ public void onEntityDamage(EntityDamageEvent event) {
processingDamageIds.add(entityId);
try {
- BlightedEntity owner = ATTACHMENT_OWNERS.get(entityId);
+ BlightedEntity owner = EntityManager.getAttachmentOwner(entityId);
if (owner != null) {
LivingEntity ownerEntity = owner.getEntity();
if (ownerEntity == null || ownerEntity.isDead()) {
target.remove();
- ATTACHMENT_OWNERS.remove(entityId);
+ EntityManager.removeAttachmentOwner(entityId);
return;
}
@@ -124,12 +121,14 @@ public void onEntityDamage(EntityDamageEvent event) {
}
}
- if (target instanceof LivingEntity living) {
- BlightedEntity blighted = BLIGHTED_ENTITIES.get(entityId);
- if (blighted != null) {
- handleBlightedEntityDamage(blighted, living, event);
- }
+ if (!(target instanceof LivingEntity living)) {
+ return;
+ }
+ BlightedEntity blighted = EntityManager.getDirectBlightedEntity(entityId);
+ if (blighted == null) {
+ return;
}
+ handleBlightedEntityDamage(blighted, living, event);
} finally {
processingDamageIds.remove(entityId);
}
@@ -179,7 +178,7 @@ private void handleAttachmentDamage(
LivingEntity ownerEntity = owner.getEntity();
if (ownerEntity == null || ownerEntity.isDead()) {
attachmentEntity.remove();
- ATTACHMENT_OWNERS.remove(attachmentEntity.getUniqueId());
+ EntityManager.removeAttachmentOwner(attachmentEntity.getUniqueId());
return;
}
@@ -255,7 +254,7 @@ public void onEntityPotionEffect(EntityPotionEffectEvent event) {
Entity target = event.getEntity();
if (!target.getScoreboardTags().contains(FAST_PASS_TAG)) return;
- BlightedEntity owner = ATTACHMENT_OWNERS.get(target.getUniqueId());
+ BlightedEntity owner = EntityManager.getAttachmentOwner(target.getUniqueId());
if (owner == null) return;
LivingEntity ownerEntity = owner.getEntity();
@@ -295,7 +294,7 @@ public void onEntityHeal(EntityRegainHealthEvent event) {
if (!entity.getScoreboardTags().contains(FAST_PASS_TAG)) return;
UUID entityId = entity.getUniqueId();
- BlightedEntity blighted = BLIGHTED_ENTITIES.get(entityId);
+ BlightedEntity blighted = EntityManager.getDirectBlightedEntity(entityId);
if (blighted != null) {
blighted.updateBossBar();
}
@@ -307,7 +306,12 @@ public void onEntityDeath(EntityDeathEvent event) {
if (!dead.getScoreboardTags().contains(FAST_PASS_TAG)) return;
UUID uuid = dead.getUniqueId();
- boolean isAttachment = ATTACHMENT_OWNERS.remove(uuid) != null
+ BlightedEntity attachmentOwner = EntityManager.getAttachmentOwner(uuid);
+ if (attachmentOwner != null) {
+ EntityManager.removeAttachmentOwner(uuid);
+ }
+
+ boolean isAttachment = attachmentOwner != null
|| dead.getPersistentDataContainer().has(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING);
if (isAttachment) {
@@ -316,8 +320,9 @@ public void onEntityDeath(EntityDeathEvent event) {
return;
}
- BlightedEntity blighted = BLIGHTED_ENTITIES.remove(uuid);
+ BlightedEntity blighted = EntityManager.getDirectBlightedEntity(uuid);
if (blighted == null) return;
+ EntityManager.removeDirectBlightedEntity(uuid);
blighted.cleanup();
@@ -340,105 +345,11 @@ public void onChunkLoad(ChunkLoadEvent event) {
}
public static Collection getActiveEntities() {
- return List.copyOf(BLIGHTED_ENTITIES.values());
+ return EntityManager.getActiveEntities();
}
public static void rehydrateChunk(Chunk chunk) {
- Entity[] entities = chunk.getEntities();
-
- // Pass 1: rehydrate main blighted entities.
- for (Entity entity : entities) {
- if (!(entity instanceof LivingEntity living)) continue;
- if (!living.getScoreboardTags().contains(FAST_PASS_TAG)) continue;
-
- PersistentDataContainer persistentDataContainer = living.getPersistentDataContainer();
- if (!persistentDataContainer.has(ENTITY_ID_KEY, PersistentDataType.STRING)) continue;
-
- BlightedEntity existing = BLIGHTED_ENTITIES.get(living.getUniqueId());
- if (existing != null) {
- if (existing.getEntity() != living) {
- existing.attachToExisting(living);
- }
- continue;
- }
-
- String entityId = persistentDataContainer.get(ENTITY_ID_KEY, PersistentDataType.STRING);
- BlightedEntity prototype = EntitiesRegistry.get(entityId);
- if (prototype == null) continue;
-
- prototype.clone().attachToExisting(living);
- }
-
- // Pass 2: re-register attachment entities carrying ATTACHMENT_OWNER_KEY.
- for (Entity entity : entities) {
- if (!entity.getScoreboardTags().contains(FAST_PASS_TAG)) continue;
-
- PersistentDataContainer persistentDataContainer = entity.getPersistentDataContainer();
- if (!persistentDataContainer.has(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING)) continue;
-
- String ownerUuidString = persistentDataContainer.get(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING);
- String roleString = persistentDataContainer.get(ATTACHMENT_ROLE_KEY, PersistentDataType.STRING);
- if (ownerUuidString == null || roleString == null) continue;
-
- UUID ownerUuid;
- try {
- ownerUuid = UUID.fromString(ownerUuidString);
- } catch (IllegalArgumentException _) {
- continue;
- }
-
- BlightedEntity owner = BLIGHTED_ENTITIES.get(ownerUuid);
- if (owner == null) continue;
-
- AttachmentRole role;
- try {
- role = AttachmentRole.valueOf(roleString);
- } catch (IllegalArgumentException _) {
- role = AttachmentRole.SUBORDINATE;
- }
-
- Double offsetX = persistentDataContainer.get(ATTACHMENT_OFFSET_X_KEY, PersistentDataType.DOUBLE);
- Double offsetY = persistentDataContainer.get(ATTACHMENT_OFFSET_Y_KEY, PersistentDataType.DOUBLE);
- Double offsetZ = persistentDataContainer.get(ATTACHMENT_OFFSET_Z_KEY, PersistentDataType.DOUBLE);
- Vector offset = new Vector(
- offsetX != null ? offsetX : 0.0,
- offsetY != null ? offsetY : 0.0,
- offsetZ != null ? offsetZ : 0.0
- );
-
- Byte yawByte = persistentDataContainer.get(ATTACHMENT_SYNC_YAW_KEY, PersistentDataType.BYTE);
- Byte pitchByte = persistentDataContainer.get(ATTACHMENT_SYNC_PITCH_KEY, PersistentDataType.BYTE);
- boolean syncYaw = yawByte == null || yawByte == 1;
- boolean syncPitch = pitchByte != null && pitchByte == 1;
-
- owner.attachments.removeIf(a -> a.entity() != null && a.entity().getUniqueId().equals(entity.getUniqueId()));
- owner.attachments.add(new EntityAttachment(entity, role, offset, syncYaw, syncPitch));
- registerAttachment(entity, owner);
- }
-
- // Pass 3: Purge orphan attachments whose owner entity no longer exists.
- Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(), () -> {
- if (!chunk.isLoaded()) return;
- for (Entity entity : chunk.getEntities()) {
- if (!entity.getScoreboardTags().contains(FAST_PASS_TAG)) continue;
- PersistentDataContainer persistentDataContainer = entity.getPersistentDataContainer();
- if (!persistentDataContainer.has(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING)) continue;
-
- String ownerUuidString = persistentDataContainer.get(ATTACHMENT_OWNER_KEY, PersistentDataType.STRING);
- if (ownerUuidString == null) continue;
-
- try {
- UUID ownerUuid = UUID.fromString(ownerUuidString);
- BlightedEntity owner = BLIGHTED_ENTITIES.get(ownerUuid);
- if (owner == null || owner.getEntity() == null || !owner.getEntity().isValid()) {
- entity.remove();
- ATTACHMENT_OWNERS.remove(entity.getUniqueId());
- }
- } catch (IllegalArgumentException _) {
- entity.remove();
- }
- }
- }, 3L);
+ EntityManager.rehydrateChunk(chunk);
}
private Player getPlayerDamager(Entity damager) {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java
new file mode 100644
index 00000000..8f8eff20
--- /dev/null
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java
@@ -0,0 +1,61 @@
+package fr.moussax.blightedSMP.engine.entities.spawnable.engine;
+
+import fr.moussax.blightedSMP.engine.entities.spawnable.SpawnableEntity;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.jspecify.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Utility for evaluating spawn conditions and selecting spawnable entity candidates weighted by probability.
+ */
+public final class SpawnEvaluator {
+
+ private SpawnEvaluator() {}
+
+ /**
+ * Evaluates a list of candidate entities against a target location and selects an eligible entity weighted by probability.
+ *
+ * @param candidates candidate spawnable entity prototypes
+ * @param location target spawn location
+ * @param world target world
+ * @param random random number generator
+ * @return selected entity definition, or {@code null} if no spawn condition was met or the roll failed
+ */
+ @Nullable
+ public static SpawnableEntity selectCandidate(List candidates, Location location, World world, ThreadLocalRandom random) {
+ if (candidates == null || candidates.isEmpty() || location == null || world == null) {
+ return null;
+ }
+
+ List eligible = null;
+ for (SpawnableEntity entity : candidates) {
+ if (!entity.canSpawnAt(location, world)) continue;
+ if (eligible == null) eligible = new ArrayList<>(candidates.size());
+ eligible.add(entity);
+ }
+
+ if (eligible == null) return null;
+
+ double totalChance = 0.0;
+ for (SpawnableEntity entity : eligible) {
+ totalChance += entity.getSpawnProbability();
+ }
+
+ if (random.nextDouble() >= Math.min(totalChance, 1.0)) return null;
+
+ double selectionRoll = random.nextDouble() * totalChance;
+ double cumulative = 0.0;
+ for (SpawnableEntity entity : eligible) {
+ cumulative += entity.getSpawnProbability();
+ if (selectionRoll < cumulative) {
+ return entity;
+ }
+ }
+
+ return null;
+ }
+}
From 72fb86075f5014da3ab8913ef441825e456f6ce9 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Mon, 28 Sep 2026 23:01:02 +0200
Subject: [PATCH 15/31] (2/4) refactor(entities): consolidate prototype
tracking under EntitiesRegistry
Unify custom blighted entity prototype registration within EntitiesRegistry and convert SpawnableEntitiesRegistry into a delegating read-only view.
---
.../entities/registry/EntitiesRegistry.java | 66 ++++++++++++++++---
.../registry/SpawnableEntitiesRegistry.java | 42 +++++++-----
2 files changed, 85 insertions(+), 23 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java
index 2249d2c8..90a1e1f3 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java
@@ -1,10 +1,10 @@
package fr.moussax.blightedSMP.engine.entities.registry;
+import fr.moussax.bedrock.utils.debug.Log;
import fr.moussax.blightedSMP.engine.entities.BlightedEntity;
import fr.moussax.blightedSMP.engine.entities.spawnable.SpawnableEntity;
import fr.moussax.blightedSMP.registry.EngineRegistry;
import fr.moussax.blightedSMP.registry.RegistryModule;
-import fr.moussax.bedrock.utils.debug.Log;
import org.jspecify.annotations.Nullable;
import java.util.ArrayList;
@@ -12,7 +12,7 @@
import java.util.function.Consumer;
/**
- * Central registry for all {@link BlightedEntity} prototypes.
+ * Central registry for prototype {@link BlightedEntity} instances.
*/
public final class EntitiesRegistry {
@@ -24,24 +24,34 @@ public final class EntitiesRegistry {
private EntitiesRegistry() {
}
+ /**
+ * Adds callback executed when a prototype entity is registered.
+ *
+ * @param callback callback runnable
+ */
public static void addOnRegisterCallback(Runnable callback) {
onRegisterCallbacks.add(callback);
}
+ /**
+ * Initializes registry with defined registration modules.
+ *
+ * @param modules list of registry modules
+ */
public static void initialize(List>> modules) {
clear();
REGISTRY.initialize(modules);
}
+ /**
+ * Registers entity prototype and executes registration callbacks.
+ *
+ * @param entity entity prototype to register
+ */
public static void register(BlightedEntity entity) {
if (entity == null) return;
- boolean isNew = !REGISTRY.contains(entity.getEntityId());
REGISTRY.register(entity);
- if (isNew && entity instanceof SpawnableEntity spawnable) {
- SpawnableEntitiesRegistry.register(spawnable);
- }
-
onRegisterCallbacks.forEach(callback -> {
try {
callback.run();
@@ -51,21 +61,61 @@ public static void register(BlightedEntity entity) {
});
}
+ /**
+ * Retrieves cloned instance of registered entity prototype by ID.
+ *
+ * @param entityId target entity identifier
+ * @return cloned entity instance, or {@code null} if untracked
+ */
@Nullable
public static BlightedEntity get(String entityId) {
BlightedEntity prototype = REGISTRY.get(entityId);
return prototype != null ? prototype.clone() : null;
}
+ /**
+ * Retrieves cloned instance of registered spawnable entity prototype by ID.
+ *
+ * @param entityId target entity identifier
+ * @return cloned spawnable entity instance, or {@code null} if untracked or not spawnable
+ */
+ @Nullable
+ public static SpawnableEntity getSpawnable(String entityId) {
+ BlightedEntity entity = REGISTRY.get(entityId);
+ if (!(entity instanceof SpawnableEntity spawnable)) {
+ return null;
+ }
+ return spawnable.clone();
+ }
+
+ /**
+ * Returns list of cloned instances of all registered entity prototypes.
+ *
+ * @return list of cloned entity prototypes
+ */
public static List getAll() {
return REGISTRY.getAll().stream()
.map(BlightedEntity::clone)
.toList();
}
+ /**
+ * Returns list of cloned instances of all registered spawnable entity prototypes.
+ *
+ * @return list of cloned spawnable entity prototypes
+ */
+ public static List getSpawnables() {
+ return REGISTRY.getAll().stream()
+ .filter(SpawnableEntity.class::isInstance)
+ .map(e -> ((SpawnableEntity) e).clone())
+ .toList();
+ }
+
+ /**
+ * Clears all registered entity prototypes and registration callbacks.
+ */
public static void clear() {
REGISTRY.clear();
- SpawnableEntitiesRegistry.clear();
onRegisterCallbacks.clear();
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java
index bb6146bd..2ad6dd1d 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java
@@ -3,37 +3,49 @@
import fr.moussax.blightedSMP.engine.entities.spawnable.SpawnableEntity;
import org.jspecify.annotations.Nullable;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+/**
+ * Convenience view delegating spawnable entity queries to {@link EntitiesRegistry}.
+ */
public final class SpawnableEntitiesRegistry {
- private static final Map SPAWNABLE_ENTITIES = new HashMap<>();
-
- private SpawnableEntitiesRegistry() {}
-
- static void register(SpawnableEntity entity) {
- SPAWNABLE_ENTITIES.put(entity.getEntityId(), entity);
+ private SpawnableEntitiesRegistry() {
}
+ /**
+ * Retrieves cloned instance of registered spawnable entity prototype by ID.
+ *
+ * @param entityId target entity identifier
+ * @return cloned spawnable entity instance, or {@code null} if untracked or not spawnable
+ */
@Nullable
public static SpawnableEntity get(String entityId) {
- SpawnableEntity prototype = SPAWNABLE_ENTITIES.get(entityId);
- return prototype != null ? prototype.clone() : null;
+ return EntitiesRegistry.getSpawnable(entityId);
}
+ /**
+ * Returns list of cloned instances of all registered spawnable entity prototypes.
+ *
+ * @return list of cloned spawnable entity prototypes
+ */
public static List getAll() {
- return SPAWNABLE_ENTITIES.values().stream()
- .map(SpawnableEntity::clone)
- .toList();
+ return EntitiesRegistry.getSpawnables();
}
+ /**
+ * Returns total number of registered spawnable entity prototypes.
+ *
+ * @return registered spawnable entity count
+ */
public static int count() {
- return SPAWNABLE_ENTITIES.size();
+ return EntitiesRegistry.getSpawnables().size();
}
+ /**
+ * No-op delegate for compatibility; delegate clearing is handled by {@link EntitiesRegistry#clear()}.
+ */
public static void clear() {
- SPAWNABLE_ENTITIES.clear();
+ // No-op: delegate handled by EntitiesRegistry.clear()
}
}
From c65732578e534abcc4db15f56f54598ffb0aeb5f Mon Sep 17 00:00:00 2001
From: Moussa
Date: Mon, 28 Sep 2026 23:01:33 +0200
Subject: [PATCH 16/31] (3/4) refactor(entities): extract spawn selection logic
to SpawnEvaluator
Decouple probability-weighted spawn condition evaluation into SpawnEvaluator to reduce duplication across BlightedSpawnEngine and SpawnableEntitiesListener.
---
.../listeners/SpawnableEntitiesListener.java | 45 +++++++------------
.../spawnable/engine/BlightedSpawnEngine.java | 28 ++----------
2 files changed, 19 insertions(+), 54 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/SpawnableEntitiesListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/SpawnableEntitiesListener.java
index bfc3e60f..065ed9ef 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/SpawnableEntitiesListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/SpawnableEntitiesListener.java
@@ -2,6 +2,7 @@
import fr.moussax.blightedSMP.engine.entities.registry.SpawnableEntitiesRegistry;
import fr.moussax.blightedSMP.engine.entities.spawnable.SpawnableEntity;
+import fr.moussax.blightedSMP.engine.entities.spawnable.engine.SpawnEvaluator;
import fr.moussax.blightedSMP.engine.entities.spawnable.engine.SpawnMode;
import org.bukkit.Location;
import org.bukkit.World;
@@ -14,6 +15,9 @@
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
+/**
+ * Event listener replacing natural creature spawns with custom {@link SpawnableEntity} instances.
+ */
public final class SpawnableEntitiesListener implements Listener {
private volatile Map> spawnCache = Collections.emptyMap();
@@ -25,7 +29,7 @@ public void onCreatureSpawn(CreatureSpawnEvent event) {
CreatureSpawnEvent.SpawnReason reason = event.getSpawnReason();
if (reason != CreatureSpawnEvent.SpawnReason.NATURAL
- && reason != CreatureSpawnEvent.SpawnReason.REINFORCEMENTS) {
+ && reason != CreatureSpawnEvent.SpawnReason.REINFORCEMENTS) {
return;
}
@@ -36,38 +40,16 @@ public void onCreatureSpawn(CreatureSpawnEvent event) {
World world = location.getWorld();
if (world == null) return;
- List eligible = null;
- for (SpawnableEntity entity : candidates) {
- if (!entity.canSpawnAt(location, world)) continue;
- if (eligible == null) eligible = new ArrayList<>(candidates.size());
- eligible.add(entity);
- }
-
- if (eligible == null) return;
-
- ThreadLocalRandom random = ThreadLocalRandom.current();
-
- // First roll: does any replacement spawn happen at all?
- double totalChance = 0.0;
- for (SpawnableEntity entity : eligible) {
- totalChance += entity.getSpawnProbability();
- }
-
- if (random.nextDouble() >= Math.min(totalChance, 1.0)) return;
-
- // Second roll: which entity wins, weighted by individual probability.
- double selectionRoll = random.nextDouble() * totalChance;
- double cumulative = 0.0;
- for (SpawnableEntity entity : eligible) {
- cumulative += entity.getSpawnProbability();
- if (selectionRoll < cumulative) {
- event.setCancelled(true);
- entity.clone().spawn(location);
- return;
- }
+ SpawnableEntity selected = SpawnEvaluator.selectCandidate(candidates, location, world, ThreadLocalRandom.current());
+ if (selected != null) {
+ event.setCancelled(true);
+ selected.clone().spawn(location);
}
}
+ /**
+ * Rebuilds spawn candidate cache from registered spawnable entities configured for replacement or hybrid spawning.
+ */
public synchronized void rebuildCache() {
if (!cacheDirty) return;
@@ -83,6 +65,9 @@ public synchronized void rebuildCache() {
this.cacheDirty = false;
}
+ /**
+ * Marks spawn cache as dirty to trigger rebuild on the next spawn event.
+ */
public void invalidateCache() {
this.cacheDirty = true;
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/BlightedSpawnEngine.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/BlightedSpawnEngine.java
index 584be36e..b5379013 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/BlightedSpawnEngine.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/BlightedSpawnEngine.java
@@ -125,30 +125,10 @@ private void attemptSpawnInChunk(Chunk chunk, World world, ThreadLocalRandom ran
Location location = new Location(world, x + 0.5, y, z + 0.5);
- List eligible = null;
- for (SpawnableEntity entity : cachedIndependentEntities) {
- if (!entity.canSpawnAt(location, world)) continue;
- if (eligible == null) eligible = new ArrayList<>(cachedIndependentEntities.size());
- eligible.add(entity);
- }
-
- if (eligible == null) continue;
-
- double totalChance = 0.0;
- for (SpawnableEntity entity : eligible) {
- totalChance += entity.getSpawnProbability();
- }
-
- if (random.nextDouble() >= Math.min(totalChance, 1.0)) continue;
-
- double selectionRoll = random.nextDouble() * totalChance;
- double cumulative = 0.0;
- for (SpawnableEntity entity : eligible) {
- cumulative += entity.getSpawnProbability();
- if (selectionRoll < cumulative) {
- entity.clone().spawn(location);
- return; // Stop scanning column once an entity spawns
- }
+ SpawnableEntity selected = SpawnEvaluator.selectCandidate(cachedIndependentEntities, location, world, random);
+ if (selected != null) {
+ selected.clone().spawn(location);
+ return; // Stop scanning column once an entity spawns
}
}
}
From def1c4031a9f89069947f34846e91cc88743fb1f Mon Sep 17 00:00:00 2001
From: Moussa
Date: Mon, 28 Sep 2026 23:01:56 +0200
Subject: [PATCH 17/31] (4/4) feat(entities): enhance EntityLootTableBuilder DX
and streamline mob loot definitions
Add type-safe BlightedItem support, default COMMON rarity fallbacks, and a symmetrical 5-tier overload hierarchy to EntityLootTableBuilder. Update custom mob definitions to consume the streamlined loot table builder API.
---
.../content/entities/BlightedEntities.java | 3 +-
.../entities/bosses/CorruptedChampion.java | 26 +-
.../blightsworn/BlightswornBogged.java | 11 +-
.../blightsworn/BlightswornDrowned.java | 10 +-
.../factions/blightsworn/BlightswornHusk.java | 6 +-
.../blightsworn/BlightswornParched.java | 8 +-
.../blightsworn/BlightswornPiglin.java | 8 +-
.../blightsworn/BlightswornSkeleton.java | 8 +-
.../blightsworn/BlightswornStray.java | 11 +-
.../BlightswornWitherSkeleton.java | 10 +-
.../blightsworn/BlightswornZombie.java | 12 +-
.../BlightswornZombifiedPiglin.java | 8 +-
.../factions/celestial/CelestialCreature.java | 20 +-
.../factions/celestial/CelestialEnderman.java | 1 +
.../content/entities/powerful/Endersent.java | 8 +-
.../content/entities/powerful/Illusioner.java | 16 +-
.../content/entities/powerful/Watchling.java | 8 +-
.../entities/EntityLootTableBuilder.java | 435 ++++++++++++++----
18 files changed, 440 insertions(+), 169 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/BlightedEntities.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/BlightedEntities.java
index d5253c90..87d6dac8 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/BlightedEntities.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/BlightedEntities.java
@@ -3,6 +3,8 @@
import fr.moussax.blightedSMP.content.entities.bosses.CorruptedChampion;
import fr.moussax.blightedSMP.content.entities.factions.blightsworn.*;
import fr.moussax.blightedSMP.content.entities.powerful.Endersent;
+import fr.moussax.blightedSMP.content.entities.powerful.Illusioner;
+import fr.moussax.blightedSMP.content.entities.powerful.Watchling;
import fr.moussax.blightedSMP.engine.entities.BlightedEntity;
import fr.moussax.blightedSMP.registry.RegistryModule;
@@ -22,7 +24,6 @@ public void register(Consumer registry) {
registry.accept(new BlightswornWitherSkeleton());
registry.accept(new BlightswornZombie());
registry.accept(new BlightswornZombifiedPiglin());
-
registry.accept(new CorruptedChampion());
registry.accept(new Endersent());
registry.accept(new Watchling());
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/bosses/CorruptedChampion.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/bosses/CorruptedChampion.java
index 4b2cefbb..66ec294b 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/bosses/CorruptedChampion.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/bosses/CorruptedChampion.java
@@ -1,14 +1,13 @@
package fr.moussax.blightedSMP.content.entities.bosses;
+import fr.moussax.bedrock.utils.ItemBuilder;
+import fr.moussax.bedrock.utils.debug.Log;
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.engine.entities.BlightedEntity;
import fr.moussax.blightedSMP.engine.entities.defense.DamageType;
import fr.moussax.blightedSMP.engine.entities.defense.EntityImmunities;
import fr.moussax.blightedSMP.engine.entities.defense.EntityResistance;
-import fr.moussax.blightedSMP.engine.entities.defense.EntityResistances;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
-import fr.moussax.bedrock.utils.ItemBuilder;
-import fr.moussax.bedrock.utils.debug.Log;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
@@ -25,13 +24,14 @@
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
@EntityImmunities({DamageType.FALL, DamageType.MACE, DamageType.PROJECTILE})
-@EntityResistances({
- @EntityResistance(type = DamageType.MAGIC, percent = 75.0),
-})
+@EntityResistance(type = DamageType.MAGIC, percent = 75.0)
public class CorruptedChampion extends BlightedEntity {
private static final int MELEE_DAMAGE = 28;
@@ -47,7 +47,7 @@ public class CorruptedChampion extends BlightedEntity {
private static final Particle.DustOptions VOID_PURPLE = new Particle.DustOptions(Color.fromRGB(150, 40, 240), 1.2f);
private static final Particle.DustOptions CHAMPION_GOLD = new Particle.DustOptions(Color.fromRGB(255, 200, 30), 1.5f);
- private final List activeStabs = new CopyOnWriteArrayList<>();
+ private List activeStabs = new CopyOnWriteArrayList<>();
private int currentPhase = 1;
public CorruptedChampion() {
@@ -257,7 +257,7 @@ private void stabTargetPlayers() {
return;
}
- BlightedPlayer blightedTarget = BlightedPlayer.getBlightedPlayer(target);
+ BlightedPlayer blightedTarget = BlightedPlayer.get(target);
if (blightedTarget == null) {
return;
}
@@ -778,13 +778,7 @@ public String getEntityId() {
@Override
public CorruptedChampion clone() {
CorruptedChampion clone = (CorruptedChampion) super.clone();
- try {
- var activeStabsField = CorruptedChampion.class.getDeclaredField("activeStabs");
- activeStabsField.setAccessible(true);
- activeStabsField.set(clone, new CopyOnWriteArrayList<>());
- } catch (Exception e) {
- throw new RuntimeException("Failed to clone sword lists", e);
- }
+ clone.activeStabs = new CopyOnWriteArrayList<>();
return clone;
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornBogged.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornBogged.java
index d6eccf00..91e70f1a 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornBogged.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornBogged.java
@@ -26,18 +26,17 @@ public BlightswornBogged() {
setDroppedExp(12);
itemInMainHand = new ItemStack(Material.BOW);
setLootTable(new EntityLootTableBuilder()
- .addLoot(Material.BONE, 2, 4, 1.0, COMMON)
- .addLoot(Material.ARROW, 2, 5, 1.0, COMMON)
+ .addLoot(Material.BONE, 2, 4, 1.0)
+ .addLoot(Material.ARROW, 2, 5, 1.0)
.addLoot(Material.TIPPED_ARROW,
builder -> builder.setItemMeta(
meta -> ((PotionMeta) meta).setBasePotionType(PotionType.POISON)),
1,
3,
- 0.4,
- UNCOMMON
+ 0.4
)
- .addDamagedLoot(Material.BOW, 0.10, 0.75, 0.15, RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addDamagedItem(Material.BOW, 0.10, 0.75, 0.15, RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build());
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornDrowned.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornDrowned.java
index b5144fcc..d51c9826 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornDrowned.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornDrowned.java
@@ -37,11 +37,11 @@ public BlightswornDrowned() {
setDamage(6);
setDroppedExp(10);
setLootTable(new EntityLootTableBuilder()
- .addLoot(Material.ROTTEN_FLESH, 2, 5, 1.0, COMMON)
- .addLoot(Material.COPPER_INGOT, 1, 3, 0.4, UNCOMMON)
- .addLoot(Material.NAUTILUS_SHELL, 1, 0.08, RARE)
- .addDamagedLoot(Material.TRIDENT, 0.05, 0.80, 0.02, VERY_RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addLoot(Material.ROTTEN_FLESH, 2, 5, 1.0)
+ .addLoot(Material.COPPER_INGOT, 1, 3, 0.4)
+ .addLoot(Material.NAUTILUS_SHELL, 0.08, RARE)
+ .addDamagedItem(Material.TRIDENT, 0.05, 0.80, 0.02, VERY_RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornHusk.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornHusk.java
index 05200ce2..1a977e00 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornHusk.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornHusk.java
@@ -19,10 +19,10 @@ public BlightswornHusk() {
setDamage(6);
setDroppedExp(12);
setLootTable(new EntityLootTableBuilder()
- .addLoot(Material.ROTTEN_FLESH, 2, 5, 1.0, COMMON)
- .addLoot(Material.SAND, 1, 3, 0.3, UNCOMMON)
+ .addLoot(Material.ROTTEN_FLESH, 2, 5, 1.0)
+ .addLoot(Material.SAND, 1, 3, 0.3)
.addLoot(Material.IRON_INGOT, 1, 2, 0.1, RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornParched.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornParched.java
index 704038c1..82bf55f5 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornParched.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornParched.java
@@ -24,10 +24,10 @@ public BlightswornParched() {
setDamage(6);
setDroppedExp(12);
setLootTable(new EntityLootTableBuilder()
- .addLoot(Material.BONE, 2, 5, 1.0, COMMON)
- .addLoot(Material.ARROW, 2, 5, 1.0, COMMON)
- .addDamagedLoot(Material.BOW, 0.10, 0.75, 0.15, RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addLoot(Material.BONE, 2, 5, 1.0)
+ .addLoot(Material.ARROW, 2, 5, 1.0)
+ .addDamagedItem(Material.BOW, 0.10, 0.75, 0.15, RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornPiglin.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornPiglin.java
index 9050e8bf..59923163 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornPiglin.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornPiglin.java
@@ -26,10 +26,10 @@ public BlightswornPiglin() {
super("BLIGHTSWORN_PIGLIN", "Blightsworn Piglin", EntityType.PIGLIN);
itemInMainHand = new ItemStack(Material.GOLDEN_SWORD);
setLootTable(new EntityLootTableBuilder()
- .addLoot(Material.GOLD_NUGGET, 2, 6, 1.0, COMMON)
- .addLoot(Material.GOLD_INGOT, 1, 3, 0.4, UNCOMMON)
- .addDamagedLoot(Material.CROSSBOW, 0.10, 0.80, 0.1, RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addLoot(Material.GOLD_NUGGET, 2, 6, 1.0)
+ .addLoot(Material.GOLD_INGOT, 1, 3, 0.4)
+ .addDamagedItem(Material.CROSSBOW, 0.10, 0.80, 0.1, RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
setDamage(8);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornSkeleton.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornSkeleton.java
index ce5f09b5..5034ec0e 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornSkeleton.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornSkeleton.java
@@ -24,10 +24,10 @@ public BlightswornSkeleton() {
setDamage(6);
setDroppedExp(12);
setLootTable(new EntityLootTableBuilder()
- .addLoot(Material.BONE, 2, 5, 1.0, COMMON)
- .addLoot(Material.ARROW, 2, 5, 1.0, COMMON)
- .addDamagedLoot(Material.BOW, 0.1, 0.8, 0.15, RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addLoot(Material.BONE, 2, 5, 1.0)
+ .addLoot(Material.ARROW, 2, 5, 1.0)
+ .addDamagedItem(Material.BOW, 0.1, 0.8, 0.15, RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornStray.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornStray.java
index 4988c5d7..932b8f5f 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornStray.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornStray.java
@@ -20,18 +20,17 @@ public BlightswornStray() {
setDamage(6);
setDroppedExp(12);
setLootTable(new EntityLootTableBuilder()
- .setMaxDrop(4)
- .addLoot(Material.BONE, 2, 5, 1.0, COMMON)
- .addLoot(Material.ARROW, 2, 5, 1.0, COMMON)
+ .maxDrops(4)
+ .addLoot(Material.BONE, 2, 5, 1.0)
+ .addLoot(Material.ARROW, 2, 5, 1.0)
.addLoot(Material.TIPPED_ARROW, builder -> builder.setItemMeta(
meta -> ((PotionMeta) meta).setBasePotionType(PotionType.SLOWNESS)
),
1,
3,
- 0.4,
- UNCOMMON
+ 0.4
)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornWitherSkeleton.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornWitherSkeleton.java
index 86937edc..4a48cade 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornWitherSkeleton.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornWitherSkeleton.java
@@ -25,11 +25,11 @@ public final class BlightswornWitherSkeleton extends BlightswornEliteArchetype {
public BlightswornWitherSkeleton() {
super("BLIGHTSWORN_WITHER_SKELETON", "Blightsworn Wither Skeleton", EntityType.WITHER_SKELETON);
setLootTable(new EntityLootTableBuilder()
- .setMaxDrop(4)
- .addLoot(Material.BONE, 2, 5, 1.0, COMMON)
- .addLoot(Material.COAL, 1, 3, 0.5, UNCOMMON)
- .addLoot(Material.WITHER_SKELETON_SKULL, 1, 0.03, VERY_RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .maxDrops(4)
+ .addLoot(Material.BONE, 2, 5, 1.0)
+ .addLoot(Material.COAL, 1, 3, 0.5)
+ .addLoot(Material.WITHER_SKELETON_SKULL, 0.03, VERY_RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombie.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombie.java
index 0b1be581..3b1bbaf6 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombie.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombie.java
@@ -16,12 +16,12 @@ public BlightswornZombie() {
setDamage(6);
setDroppedExp(12);
setLootTable(new EntityLootTableBuilder()
- .setMaxDrop(3)
- .addLoot(Material.ROTTEN_FLESH, 1, 2, 1.0, COMMON)
- .addLoot(Material.POTATO, 1, 0.025, UNCOMMON)
- .addLoot(Material.CARROT, 1, 0.025, UNCOMMON)
- .addLoot(Material.IRON_INGOT, 1, 0.02, RARE)
- .addGemsLoot(2, 0.01, VERY_RARE)
+ .maxDrops(3)
+ .addLoot(Material.ROTTEN_FLESH, 1, 2, 1.0)
+ .addLoot(Material.POTATO, 0.025)
+ .addLoot(Material.CARROT, 0.025)
+ .addLoot(Material.IRON_INGOT, 0.02, RARE)
+ .addGems(2, 0.01, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombifiedPiglin.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombifiedPiglin.java
index 715ab7ca..30a4e971 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombifiedPiglin.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/blightsworn/BlightswornZombifiedPiglin.java
@@ -26,11 +26,11 @@ public BlightswornZombifiedPiglin() {
setDamage(8);
setDroppedExp(16);
setLootTable(new EntityLootTableBuilder()
- .setMaxDrop(3)
- .addLoot(Material.ROTTEN_FLESH, 2, 6, 1.0, COMMON)
- .addLoot(Material.GOLD_NUGGET, 2, 6, 1.0, COMMON)
+ .maxDrops(3)
+ .addLoot(Material.ROTTEN_FLESH, 2, 6, 1.0)
+ .addLoot(Material.GOLD_NUGGET, 2, 6, 1.0)
.addLoot(Material.GOLD_INGOT, 1, 2, 0.15, RARE)
- .addGemsLoot(5, 0.04, VERY_RARE)
+ .addGems(5, 0.04, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialCreature.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialCreature.java
index 62f6e59f..7579fd35 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialCreature.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialCreature.java
@@ -1,4 +1,22 @@
package fr.moussax.blightedSMP.content.entities.factions.celestial;
-public abstract class CelestialCreature {
+import fr.moussax.blightedSMP.engine.entities.spawnable.SpawnableEntity;
+import org.bukkit.Location;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+public abstract class CelestialCreature extends SpawnableEntity {
+ protected CelestialCreature(String entityId, String name, int maxHealth, EntityType entityType, double probability) {
+ super(entityId, name, maxHealth, entityType, probability);
+ }
+
+ @Override
+ public LivingEntity spawn(Location location) {
+ LivingEntity entity = super.spawn(location);
+ entity.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, PotionEffect.INFINITE_DURATION, 1));
+ entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, PotionEffect.INFINITE_DURATION, 1));
+ return entity;
+ }
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialEnderman.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialEnderman.java
index 58e3287a..b6c0d36f 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialEnderman.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/factions/celestial/CelestialEnderman.java
@@ -1,4 +1,5 @@
package fr.moussax.blightedSMP.content.entities.factions.celestial;
+
public class CelestialEnderman {
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Endersent.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Endersent.java
index 6e1d3148..ecf4d69a 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Endersent.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Endersent.java
@@ -40,11 +40,11 @@ public Endersent() {
addAttribute(Attribute.MOVEMENT_SPEED, 0.25);
setLootTable(new EntityLootTableBuilder()
- .setMaxDrop(2)
- .addLoot(Material.ENDER_PEARL, 4, 8, 1.0, COMMON)
- .addLoot(Material.ENDER_EYE, 1, 3, 0.31, UNCOMMON)
+ .maxDrops(2)
+ .addLoot(Material.ENDER_PEARL, 4, 8, 1.0)
+ .addLoot(Material.ENDER_EYE, 1, 3, 0.31)
.addLoot("ENCHANTED_ENDER_PEARL", 1, 4, 0.11, RARE)
- .addGemsLoot(30, 0.03, VERY_RARE)
+ .addGems(30, 0.03, VERY_RARE)
.build()
);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Illusioner.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Illusioner.java
index 22582aca..a4b8a84e 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Illusioner.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Illusioner.java
@@ -1,4 +1,4 @@
-package fr.moussax.blightedSMP.content.entities;
+package fr.moussax.blightedSMP.content.entities.powerful;
import fr.moussax.blightedSMP.engine.entities.EntityLootTableBuilder;
import fr.moussax.blightedSMP.engine.entities.components.impl.ShieldComponent;
@@ -17,16 +17,16 @@ public Illusioner() {
setDamage(12);
this.lootTable = new EntityLootTableBuilder()
- .addLoot(Material.SPECTRAL_ARROW, 4, 12, 0.6, EntityLootRarity.COMMON)
- .addLoot(Material.GLASS_BOTTLE, 1, 2, 0.4, EntityLootRarity.COMMON)
- .addLoot(Material.TOTEM_OF_UNDYING, 1, 0.02, EntityLootRarity.VERY_RARE)
- .addLoot(Material.OMINOUS_BOTTLE, 1, 0.15, EntityLootRarity.UNCOMMON)
- .addGemsLoot(12, 0.25, EntityLootRarity.UNCOMMON)
- .addEnchantedBookLoot(
+ .maxDrops(4)
+ .addLoot(Material.SPECTRAL_ARROW, 4, 12, 0.6)
+ .addLoot(Material.GLASS_BOTTLE, 1, 2, 0.4)
+ .addLoot(Material.TOTEM_OF_UNDYING, 0.02, EntityLootRarity.VERY_RARE)
+ .addLoot(Material.OMINOUS_BOTTLE, 0.15)
+ .addGems(12, 0.25)
+ .addEnchantedBook(
List.of(Enchantment.QUICK_CHARGE, Enchantment.PIERCING, Enchantment.POWER),
1, 7, 0.07, EntityLootRarity.RARE
)
- .setMaxDrop(4)
.build();
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Watchling.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Watchling.java
index 5474c9ba..69af090b 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Watchling.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/entities/powerful/Watchling.java
@@ -1,4 +1,4 @@
-package fr.moussax.blightedSMP.content.entities;
+package fr.moussax.blightedSMP.content.entities.powerful;
import fr.moussax.blightedSMP.content.utils.ai.EndermanAI;
import fr.moussax.blightedSMP.engine.entities.EntityLootTableBuilder;
@@ -34,9 +34,9 @@ public Watchling() {
setDroppedExp(10);
setLootTable(new EntityLootTableBuilder()
- .setMaxDrop(2)
- .addLoot(Material.ENDER_PEARL, 1, 2, 1.0, COMMON)
- .addGemsLoot(5, 0.03, VERY_RARE)
+ .maxDrops(2)
+ .addLoot(Material.ENDER_PEARL, 1, 2, 1.0)
+ .addGems(5, 0.03, VERY_RARE)
.build()
);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityLootTableBuilder.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityLootTableBuilder.java
index 5da0b4dc..ccd2278e 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityLootTableBuilder.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityLootTableBuilder.java
@@ -1,5 +1,7 @@
package fr.moussax.blightedSMP.engine.entities;
+import fr.moussax.bedrock.utils.ItemBuilder;
+import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.loot.LootCondition;
import fr.moussax.blightedSMP.engine.loot.LootEntry;
import fr.moussax.blightedSMP.engine.loot.LootTable;
@@ -10,7 +12,6 @@
import fr.moussax.blightedSMP.engine.loot.results.ItemResult;
import fr.moussax.blightedSMP.engine.loot.results.gems.GemsResult;
import fr.moussax.blightedSMP.engine.loot.strategies.LootingAwareProbabilisticStrategy;
-import fr.moussax.bedrock.utils.ItemBuilder;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.enchantments.Enchantment;
@@ -44,31 +45,164 @@ public final class EntityLootTableBuilder {
private int maxDrops = 3;
/**
- * Adds a registered item loot entry with a variable quantity range.
+ * Adds custom blighted item drop with fixed quantity of 1.
+ *
+ * @param item custom blighted item
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(BlightedItem item, double dropChance) {
+ if (item == null) return this;
+ return addLoot(
+ item.getItemId(),
+ 1,
+ 1,
+ dropChance,
+ EntityLootRarity.COMMON,
+ LootCondition.alwaysTrue()
+ );
+ }
+
+ /**
+ * Adds custom blighted item drop with fixed quantity of 1 and rarity feedback.
+ *
+ * @param item custom blighted item
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @param rarity rarity tier for feedback
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(BlightedItem item, double dropChance, EntityLootRarity rarity) {
+ if (item == null) return this;
+ return addLoot(item.getItemId(), 1, 1, dropChance, rarity, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds custom blighted item drop with quantity range.
+ *
+ * @param item custom blighted item
+ * @param minAmount minimum drop quantity
+ * @param maximumAmount maximum drop quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(BlightedItem item, int minAmount, int maximumAmount, double dropChance) {
+ if (item == null) return this;
+ return addLoot(item.getItemId(), minAmount, maximumAmount, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds custom blighted item drop with quantity range and rarity feedback.
+ *
+ * @param item custom blighted item
+ * @param minimumAmount minimum drop quantity
+ * @param maximumAmount maximum drop quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @param rarity rarity tier for feedback
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(BlightedItem item, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity) {
+ if (item == null) return this;
+ return addLoot(item.getItemId(), minimumAmount, maximumAmount, dropChance, rarity, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds custom blighted item drop with quantity range, rarity feedback, and eligibility condition.
*
- * @param itemId registry ID of the item
+ * @param item custom blighted item
* @param minimumAmount minimum drop quantity
* @param maximumAmount maximum drop quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
+ * @param condition eligibility condition
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(
+ BlightedItem item,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity,
+ LootCondition condition
+ ) {
+ if (item == null) return this;
+ return addLoot(item.getItemId(), minimumAmount, maximumAmount, dropChance, rarity, condition);
+ }
+
+ /**
+ * Adds registered item drop with fixed quantity of 1.
+ *
+ * @param itemId registered item identifier
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(String itemId, double dropChance) {
+ return addLoot(itemId, 1, 1, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds registered item drop with fixed quantity of 1 and rarity feedback.
+ *
+ * @param itemId registered item identifier
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addLoot(String itemId, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addLoot(String itemId, double dropChance, EntityLootRarity rarity) {
+ return addLoot(itemId, 1, 1, dropChance, rarity, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds registered item drop with quantity range.
+ *
+ * @param itemId registered item identifier
+ * @param minimumAmount minimum drop quantity
+ * @param maximumAmount maximum drop quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(String itemId, int minimumAmount, int maximumAmount, double dropChance) {
+ return addLoot(itemId, minimumAmount, maximumAmount, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds registered item drop with quantity range and rarity feedback.
+ *
+ * @param itemId registered item identifier
+ * @param minimumAmount minimum drop quantity
+ * @param maximumAmount maximum drop quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @param rarity rarity tier for feedback
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(
+ String itemId,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
return addLoot(itemId, minimumAmount, maximumAmount, dropChance, rarity, LootCondition.alwaysTrue());
}
/**
- * Adds a registered item loot entry with a variable quantity range and selection condition.
+ * Adds registered item drop with quantity range, rarity feedback, and eligibility condition.
*
- * @param itemId registry ID of the item
+ * @param itemId registered item identifier
* @param minimumAmount minimum drop quantity
* @param maximumAmount maximum drop quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
- * @param condition condition required for eligibility
+ * @param condition eligibility condition
* @return this builder
*/
- public EntityLootTableBuilder addLoot(String itemId, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity, LootCondition condition) {
+ public EntityLootTableBuilder addLoot(
+ String itemId,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity,
+ LootCondition condition
+ ) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(
@@ -83,58 +217,85 @@ public EntityLootTableBuilder addLoot(String itemId, int minimumAmount, int maxi
}
/**
- * Adds a registered item loot entry with a fixed quantity.
+ * Adds vanilla material item drop with fixed quantity of 1.
*
- * @param itemId registry ID of the item
- * @param amount drop quantity
+ * @param material item material
* @param dropChance selection probability (0.0 to 1.0)
- * @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addLoot(String itemId, int amount, double dropChance, EntityLootRarity rarity) {
- return addLoot(itemId, amount, amount, dropChance, rarity, LootCondition.alwaysTrue());
+ public EntityLootTableBuilder addLoot(Material material, double dropChance) {
+ return addLoot(material, 1, 1, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
}
/**
- * Adds a registered item loot entry with a fixed quantity and selection condition.
+ * Adds vanilla material item drop with fixed quantity of 1 and rarity feedback.
*
- * @param itemId registry ID of the item
- * @param amount drop quantity
+ * @param material item material
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
- * @param condition condition required for eligibility
* @return this builder
*/
- public EntityLootTableBuilder addLoot(String itemId, int amount, double dropChance, EntityLootRarity rarity, LootCondition condition) {
- return addLoot(itemId, amount, amount, dropChance, rarity, condition);
+ public EntityLootTableBuilder addLoot(Material material, double dropChance, EntityLootRarity rarity) {
+ return addLoot(material, 1, 1, dropChance, rarity, LootCondition.alwaysTrue());
}
/**
- * Adds a material item loot entry with a variable quantity range.
+ * Adds vanilla material item drop with quantity range.
*
- * @param material material to drop
+ * @param material item material
+ * @param minimumAmount minimum drop quantity
+ * @param maximumAmount maximum drop quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance
+ ) {
+ return addLoot(material, minimumAmount, maximumAmount, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds vanilla material item drop with quantity range and rarity feedback.
+ *
+ * @param material item material
* @param minimumAmount minimum drop quantity
* @param maximumAmount maximum drop quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
return addLoot(material, minimumAmount, maximumAmount, dropChance, rarity, LootCondition.alwaysTrue());
}
/**
- * Adds a material item loot entry with a variable quantity range and selection condition.
+ * Adds vanilla material item drop with quantity range, rarity feedback, and eligibility condition.
*
- * @param material material to drop
+ * @param material item material
* @param minimumAmount minimum drop quantity
* @param maximumAmount maximum drop quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
- * @param condition condition required for eligibility
+ * @param condition eligibility condition
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity, LootCondition condition) {
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity,
+ LootCondition condition
+ ) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(
@@ -149,60 +310,98 @@ public EntityLootTableBuilder addLoot(Material material, int minimumAmount, int
}
/**
- * Adds a material item loot entry with a fixed quantity.
+ * Adds modified material item drop with fixed quantity of 1.
*
- * @param material material to drop
- * @param amount drop quantity
+ * @param material item material
+ * @param modifier item builder modification function
* @param dropChance selection probability (0.0 to 1.0)
- * @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, int amount, double dropChance, EntityLootRarity rarity) {
- return addLoot(material, amount, amount, dropChance, rarity, LootCondition.alwaysTrue());
+ public EntityLootTableBuilder addLoot(Material material, Consumer modifier, double dropChance) {
+ return addLoot(material, modifier, 1, 1, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
}
/**
- * Adds a material item loot entry with a fixed quantity and selection condition.
+ * Adds modified material item drop with fixed quantity of 1 and rarity feedback.
*
- * @param material material to drop
- * @param amount drop quantity
+ * @param material item material
+ * @param modifier item builder modification function
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
- * @param condition condition required for eligibility
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, int amount, double dropChance, EntityLootRarity rarity, LootCondition condition) {
- return addLoot(material, amount, amount, dropChance, rarity, condition);
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ Consumer modifier,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
+ return addLoot(material, modifier, 1, 1, dropChance, rarity, LootCondition.alwaysTrue());
+ }
+
+ /**
+ * Adds modified material item drop with quantity range.
+ *
+ * @param material item material
+ * @param modifier item builder modification function
+ * @param minimumAmount minimum drop quantity
+ * @param maximumAmount maximum drop quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ Consumer modifier,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance
+ ) {
+ return addLoot(material, modifier, minimumAmount, maximumAmount, dropChance, EntityLootRarity.COMMON, LootCondition.alwaysTrue());
}
/**
- * Adds a modified material item loot entry with a variable quantity range.
+ * Adds modified material item drop with quantity range and rarity feedback.
*
- * @param material material to drop
- * @param modifier function to modify the item builder
+ * @param material item material
+ * @param modifier item builder modification function
* @param minimumAmount minimum drop quantity
* @param maximumAmount maximum drop quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, Consumer modifier, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ Consumer modifier,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
return addLoot(material, modifier, minimumAmount, maximumAmount, dropChance, rarity, LootCondition.alwaysTrue());
}
/**
- * Adds a modified material item loot entry with a variable quantity range and selection condition.
+ * Adds modified material item drop with quantity range, rarity feedback, and eligibility condition.
*
- * @param material material to drop
- * @param modifier function to modify the item builder
+ * @param material item material
+ * @param modifier item builder modification function
* @param minimumAmount minimum drop quantity
* @param maximumAmount maximum drop quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
- * @param condition condition required for eligibility
+ * @param condition eligibility condition
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, Consumer modifier, int minimumAmount, int maximumAmount, double dropChance, EntityLootRarity rarity, LootCondition condition) {
+ public EntityLootTableBuilder addLoot(
+ Material material,
+ Consumer modifier,
+ int minimumAmount,
+ int maximumAmount,
+ double dropChance,
+ EntityLootRarity rarity,
+ LootCondition condition
+ ) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(
@@ -217,43 +416,29 @@ public EntityLootTableBuilder addLoot(Material material, Consumer m
}
/**
- * Adds a modified material item loot entry with a fixed quantity.
+ * Adds enchanted book drop selected from an enchantment map pool.
*
- * @param material material to drop
- * @param modifier function to modify the item builder
- * @param amount drop quantity
- * @param dropChance selection probability (0.0 to 1.0)
- * @param rarity rarity tier for feedback
- * @return this builder
- */
- public EntityLootTableBuilder addLoot(Material material, Consumer modifier, int amount, double dropChance, EntityLootRarity rarity) {
- return addLoot(material, modifier, amount, amount, dropChance, rarity, LootCondition.alwaysTrue());
- }
-
- /**
- * Adds a modified material item loot entry with a fixed quantity and selection condition.
- *
- * @param material material to drop
- * @param modifier function to modify the item builder
- * @param amount drop quantity
- * @param dropChance selection probability (0.0 to 1.0)
- * @param rarity rarity tier for feedback
- * @param condition condition required for eligibility
+ * @param enchantmentPool map of candidate enchantments to levels
+ * @param dropChance selection probability (0.0 to 1.0)
* @return this builder
*/
- public EntityLootTableBuilder addLoot(Material material, Consumer modifier, int amount, double dropChance, EntityLootRarity rarity, LootCondition condition) {
- return addLoot(material, modifier, amount, amount, dropChance, rarity, condition);
+ public EntityLootTableBuilder addEnchantedBook(Map enchantmentPool, double dropChance) {
+ return addEnchantedBook(enchantmentPool, dropChance, EntityLootRarity.COMMON);
}
/**
- * Adds an enchanted book loot entry where the enchantment and level are selected from a pool.
+ * Adds enchanted book drop selected from an enchantment map pool with rarity feedback.
*
- * @param enchantmentPool map of enchantments to levels
+ * @param enchantmentPool map of candidate enchantments to levels
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addEnchantedBookLoot(Map enchantmentPool, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addEnchantedBook(
+ Map enchantmentPool,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(
@@ -268,7 +453,25 @@ public EntityLootTableBuilder addEnchantedBookLoot(Map enc
}
/**
- * Adds an enchanted book loot entry with a level range selected from candidate enchantments.
+ * Adds enchanted book drop with level range selected from candidate enchantments.
+ *
+ * @param enchantments list of candidate enchantments
+ * @param minimumLevel minimum enchantment level
+ * @param maximumLevel maximum enchantment level
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addEnchantedBook(
+ List enchantments,
+ int minimumLevel,
+ int maximumLevel,
+ double dropChance
+ ) {
+ return addEnchantedBook(enchantments, minimumLevel, maximumLevel, dropChance, EntityLootRarity.COMMON);
+ }
+
+ /**
+ * Adds enchanted book drop with level range selected from candidate enchantments with rarity feedback.
*
* @param enchantments list of candidate enchantments
* @param minimumLevel minimum enchantment level
@@ -277,7 +480,13 @@ public EntityLootTableBuilder addEnchantedBookLoot(Map enc
* @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addEnchantedBookLoot(List enchantments, int minimumLevel, int maximumLevel, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addEnchantedBook(
+ List enchantments,
+ int minimumLevel,
+ int maximumLevel,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(
@@ -292,20 +501,48 @@ public EntityLootTableBuilder addEnchantedBookLoot(List enchantment
}
/**
- * Adds an item loot entry whose durability is rolled within a percentage range.
+ * Adds item drop with durability rolled in a percentage range.
*
- * @param material material to drop
+ * @param material item material
+ * @param minimumPercentage minimum durability percentage
+ * @param maximumPercentage maximum durability percentage
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addDamagedItem(
+ Material material,
+ double minimumPercentage,
+ double maximumPercentage,
+ double dropChance
+ ) {
+ return addDamagedItem(material, minimumPercentage, maximumPercentage, dropChance, EntityLootRarity.COMMON);
+ }
+
+ /**
+ * Adds item drop with durability rolled in a percentage range with rarity feedback.
+ *
+ * @param material item material
* @param minimumPercentage minimum durability percentage
* @param maximumPercentage maximum durability percentage
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addDamagedLoot(Material material, double minimumPercentage, double maximumPercentage, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addDamagedItem(
+ Material material,
+ double minimumPercentage,
+ double maximumPercentage,
+ double dropChance,
+ EntityLootRarity rarity
+ ) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(
- ItemResult.randomDurability(material, minimumPercentage, maximumPercentage), rarity, ENTITY_FEEDBACK_MAPPER
+ ItemResult.randomDurability(
+ material,
+ minimumPercentage,
+ maximumPercentage
+ ), rarity, ENTITY_FEEDBACK_MAPPER
),
dropChance,
AmountProvider.fixed(1),
@@ -316,14 +553,25 @@ public EntityLootTableBuilder addDamagedLoot(Material material, double minimumPe
}
/**
- * Adds a gem reward loot entry.
+ * Adds gem reward drop.
+ *
+ * @param gems gem reward quantity
+ * @param dropChance selection probability (0.0 to 1.0)
+ * @return this builder
+ */
+ public EntityLootTableBuilder addGems(int gems, double dropChance) {
+ return addGems(gems, dropChance, EntityLootRarity.COMMON);
+ }
+
+ /**
+ * Adds gem reward drop with rarity feedback.
*
- * @param gems quantity of gems granted
+ * @param gems gem reward quantity
* @param dropChance selection probability (0.0 to 1.0)
* @param rarity rarity tier for feedback
* @return this builder
*/
- public EntityLootTableBuilder addGemsLoot(int gems, double dropChance, EntityLootRarity rarity) {
+ public EntityLootTableBuilder addGems(int gems, double dropChance, EntityLootRarity rarity) {
builder.addEntry(
LootEntry.probabilistic(
new GenericFeedbackDecorator<>(new GemsResult(), rarity, ENTITY_FEEDBACK_MAPPER),
@@ -336,20 +584,31 @@ public EntityLootTableBuilder addGemsLoot(int gems, double dropChance, EntityLoo
}
/**
- * Sets the maximum number of loot drops allowed per roll.
+ * Sets maximum number of loot drops allowed per roll.
+ *
+ * @param maxDrops maximum drop count
+ * @return this builder
+ */
+ public EntityLootTableBuilder maxDrops(int maxDrops) {
+ this.maxDrops = maxDrops;
+ return this;
+ }
+
+ /**
+ * Sets maximum number of loot drops allowed per roll.
*
- * @param maxDrops maximum number of drops
+ * @param maxDrops maximum drop count
* @return this builder
*/
- public EntityLootTableBuilder setMaxDrop(int maxDrops) {
+ public EntityLootTableBuilder setMaxDrops(int maxDrops) {
this.maxDrops = maxDrops;
return this;
}
/**
- * Constructs the configured {@link LootTable} instance.
+ * Constructs configured {@link LootTable} instance.
*
- * @return a new entity loot table
+ * @return new entity loot table
*/
public LootTable build() {
return builder
From be1a05d641a385e8339a6b0bfbbfb87398d4e4a2 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 20:23:42 +0200
Subject: [PATCH 18/31] (1/2) refactor(entities): simplify task scheduling
logic in LifecycleTaskManager
---
.../engine/entities/LifecycleTaskManager.java | 57 ++++++++++---------
1 file changed, 30 insertions(+), 27 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java
index a4335e51..234a6f42 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/LifecycleTaskManager.java
@@ -113,7 +113,12 @@ private static final class ScheduledTask {
private BukkitTask currentTask;
private BukkitRunnable currentRunnable;
- private ScheduledTask(Runnable action, Supplier factory, long delayTicks, long periodTicks, boolean repeating) {
+ private ScheduledTask(
+ Runnable action,
+ Supplier factory,
+ long delayTicks,
+ long periodTicks,
+ boolean repeating) {
this.action = action;
this.factory = factory;
this.delayTicks = delayTicks;
@@ -124,38 +129,36 @@ private ScheduledTask(Runnable action, Supplier factory, long de
private void schedule(LifecycleTaskManager manager) {
cancel();
+ var plugin = BlightedSMP.getInstance();
+
if (repeating) {
if (action != null) {
- currentTask = Bukkit.getScheduler().runTaskTimer(BlightedSMP.getInstance(), action, delayTicks, periodTicks);
+ currentTask = Bukkit.getScheduler().runTaskTimer(plugin, action, delayTicks, periodTicks);
} else if (factory != null) {
currentRunnable = factory.get();
- currentTask = currentRunnable.runTaskTimer(BlightedSMP.getInstance(), delayTicks, periodTicks);
- }
- } else {
- if (action != null) {
- currentTask = Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(), () -> {
- try {
- action.run();
- } finally {
- manager.onTaskComplete(ScheduledTask.this);
- }
- }, delayTicks);
- } else if (factory != null) {
- currentRunnable = new BukkitRunnable() {
- private final BukkitRunnable inner = factory.get();
-
- @Override
- public void run() {
- try {
- if (inner != null) inner.run();
- } finally {
- manager.onTaskComplete(ScheduledTask.this);
- }
- }
- };
- currentTask = currentRunnable.runTaskLater(BlightedSMP.getInstance(), delayTicks);
+ if (currentRunnable != null) {
+ currentTask = currentRunnable.runTaskTimer(plugin, delayTicks, periodTicks);
+ }
}
+ return;
}
+
+ Runnable taskAction = action != null ? action : () -> {
+ if (factory != null) {
+ currentRunnable = factory.get();
+ if (currentRunnable != null) {
+ currentRunnable.run();
+ }
+ }
+ };
+
+ currentTask = Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ try {
+ taskAction.run();
+ } finally {
+ manager.onTaskComplete(ScheduledTask.this);
+ }
+ }, delayTicks);
}
private void cancel() {
From 3111281c5c6e861bf93e395d81dbe9d4ed4b9d5d Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 20:23:57 +0200
Subject: [PATCH 19/31] (2/2) refactor(entities): streamline damage handling
and attachment cleanup in BlightedEntitiesListener and BlightedEntity
---
.../engine/entities/BlightedEntity.java | 59 ++++++++----------
.../listeners/BlightedEntitiesListener.java | 62 +++++++++----------
2 files changed, 56 insertions(+), 65 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
index 0181ec0c..fb113cde 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
@@ -96,6 +96,7 @@ public abstract class BlightedEntity implements Cloneable {
@Setter
protected boolean isBoss = false;
+
@Getter
@Setter
protected boolean isPerformingAbility = false;
@@ -107,6 +108,7 @@ public abstract class BlightedEntity implements Cloneable {
@Getter
private EntityDefenses defenses = EntityDefenses.fromClass(getClass());
+
private boolean runtimeInitialized = false;
private boolean componentsInitialized = false;
@@ -375,6 +377,7 @@ protected final void addCoreDelayedAction(long delayTicks, Runnable action) {
* @param delayTicks delay in server ticks
* @param action task action
*/
+ @SuppressWarnings("SameParameterValue")
protected final void addPhaseDelayedAction(long delayTicks, Runnable action) {
scheduleDelayedAction(phaseTasks, delayTicks, action);
}
@@ -446,9 +449,15 @@ public List getNearbyPlayers(double radius) {
*/
public List getNearbyPlayers(Location center, double radius) {
if (!isAlive() || center == null || center.getWorld() == null) return Collections.emptyList();
- return center.getWorld().getNearbyEntities(center, radius, radius, radius,
- entity -> entity instanceof Player player && player.getGameMode() == GameMode.SURVIVAL
- ).stream()
+ return center
+ .getWorld()
+ .getNearbyEntities(
+ center,
+ radius,
+ radius,
+ radius,
+ entity -> entity instanceof Player player && player.getGameMode() == GameMode.SURVIVAL)
+ .stream()
.map(entity -> (Player) entity)
.toList();
}
@@ -472,8 +481,7 @@ public Player getNearestPlayer(double radius) {
*/
public Player getNearestPlayer(Location center, double radius) {
if (center == null) return null;
- return getNearbyPlayers(center, radius)
- .stream()
+ return getNearbyPlayers(center, radius).stream()
.min(Comparator.comparingDouble(player -> player.getLocation().distanceSquared(center)))
.orElse(null);
}
@@ -509,8 +517,7 @@ public List getNearbyBlightedPlayers(Location center, double rad
* @return nearest BlightedMC player, or {@code null}
*/
public BlightedPlayer getNearestBlightedPlayer(double radius) {
- Player target = getNearestPlayer(radius);
- return target != null ? BlightedPlayer.get(target) : null;
+ return getNearestBlightedPlayer(entity != null ? entity.getLocation() : null, radius);
}
/**
@@ -660,9 +667,9 @@ public ItemDisplay attachItemDisplay(Vector offset, Consumer config
}
Vector localOffset = offset != null ? offset : new Vector(0, 0, 0);
Location spawnLoc = entity.getLocation().clone().add(localOffset);
- ItemDisplay display = entity.getWorld().spawn(spawnLoc, ItemDisplay.class, d -> {
+ ItemDisplay display = entity.getWorld().spawn(spawnLoc, ItemDisplay.class, itemDisplay -> {
if (configurator != null) {
- configurator.accept(d);
+ configurator.accept(itemDisplay);
}
});
addAttachment(display, AttachmentRole.VISUAL, localOffset, true, false);
@@ -837,14 +844,7 @@ public void syncAttachments() {
continue;
}
- Location targetLocation = new Location(
- baseLocation.getWorld(),
- xPrime,
- yPrime,
- zPrime,
- targetYaw,
- targetPitch
- );
+ Location targetLocation = new Location(baseLocation.getWorld(), xPrime, yPrime, zPrime, targetYaw, targetPitch);
attachedEntity.teleport(targetLocation);
}
@@ -881,18 +881,17 @@ public void killAttachments(AttachmentRole role) {
return;
}
- for (EntityAttachment attachment : attachments) {
+ attachments.removeIf(attachment -> {
if (attachment.role() != role) {
- continue;
+ return false;
}
-
Entity attachmentEntity = attachment.entity();
if (attachmentEntity != null) {
EntityManager.unregisterAttachment(attachmentEntity);
attachmentEntity.remove();
}
- attachments.remove(attachment);
- }
+ return true;
+ });
}
/**
@@ -1042,14 +1041,7 @@ public void dropLoot(Location location, BlightedPlayer player) {
World world = Objects.requireNonNull(location.getWorld());
Biome biome = world.getBiome(location);
- LootContext context = new LootContext(
- player,
- world,
- biome,
- location,
- ThreadLocalRandom.current(),
- null
- );
+ LootContext context = new LootContext(player, world, biome, location, ThreadLocalRandom.current(), null);
lootTable.execute(context);
}
@@ -1276,13 +1268,16 @@ private void manageBossBarViewers() {
double rangeSquared = BOSS_BAR_RANGE * BOSS_BAR_RANGE;
for (Player player : new ArrayList<>(bossBar.getPlayers())) {
- if (!player.isOnline() || player.getWorld() != world || player.getLocation().distanceSquared(entityLocation) > rangeSquared) {
+ if (!player.isOnline()
+ || player.getWorld() != world
+ || player.getLocation().distanceSquared(entityLocation) > rangeSquared) {
bossBar.removePlayer(player);
}
}
for (Player player : world.getPlayers()) {
- if (player.getLocation().distanceSquared(entityLocation) <= rangeSquared && !bossBar.getPlayers().contains(player)) {
+ if (player.getLocation().distanceSquared(entityLocation) <= rangeSquared
+ && !bossBar.getPlayers().contains(player)) {
bossBar.addPlayer(player);
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
index 0ea11df4..fb99b785 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
@@ -101,9 +101,8 @@ public void onEntityDamage(EntityDamageEvent event) {
if (!target.getScoreboardTags().contains(FAST_PASS_TAG)) return;
UUID entityId = target.getUniqueId();
- if (processingDamageIds.contains(entityId)) return;
+ if (!processingDamageIds.add(entityId)) return;
- processingDamageIds.add(entityId);
try {
BlightedEntity owner = EntityManager.getAttachmentOwner(entityId);
if (owner != null) {
@@ -135,24 +134,24 @@ public void onEntityDamage(EntityDamageEvent event) {
}
private AttachmentRole getAttachmentRole(BlightedEntity owner, Entity attachmentEntity) {
+ if (attachmentEntity == null) {
+ return AttachmentRole.SUBORDINATE;
+ }
+
if (owner != null && owner.attachments != null) {
for (EntityAttachment attachment : owner.attachments) {
- if (attachment.entity() != null && attachment.entity().equals(attachmentEntity)) {
+ if (attachmentEntity.equals(attachment.entity())) {
return attachment.role();
}
}
}
- if (attachmentEntity != null) {
- PersistentDataContainer persistentDataContainer = attachmentEntity.getPersistentDataContainer();
- if (persistentDataContainer.has(ATTACHMENT_ROLE_KEY, PersistentDataType.STRING)) {
- String roleString = persistentDataContainer.get(ATTACHMENT_ROLE_KEY, PersistentDataType.STRING);
- if (roleString != null) {
- try {
- return AttachmentRole.valueOf(roleString);
- } catch (IllegalArgumentException _) {
- }
- }
+ PersistentDataContainer persistentDataContainer = attachmentEntity.getPersistentDataContainer();
+ String roleString = persistentDataContainer.get(ATTACHMENT_ROLE_KEY, PersistentDataType.STRING);
+ if (roleString != null) {
+ try {
+ return AttachmentRole.valueOf(roleString);
+ } catch (IllegalArgumentException _) {
}
}
return AttachmentRole.SUBORDINATE;
@@ -160,9 +159,10 @@ private AttachmentRole getAttachmentRole(BlightedEntity owner, Entity attachment
private void handleDamageDealt(EntityDamageByEntityEvent event) {
Entity rawDamager = event.getDamager();
- Entity source = (rawDamager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter)
- ? shooter
- : rawDamager;
+ Entity source =
+ (rawDamager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter)
+ ? shooter
+ : rawDamager;
BlightedEntity damager = getBlightedEntity(source);
if (damager != null) {
@@ -170,11 +170,7 @@ private void handleDamageDealt(EntityDamageByEntityEvent event) {
}
}
- private void handleAttachmentDamage(
- BlightedEntity owner,
- Entity attachmentEntity,
- EntityDamageEvent event
- ) {
+ private void handleAttachmentDamage(BlightedEntity owner, Entity attachmentEntity, EntityDamageEvent event) {
LivingEntity ownerEntity = owner.getEntity();
if (ownerEntity == null || ownerEntity.isDead()) {
attachmentEntity.remove();
@@ -215,12 +211,16 @@ private void handleBlightedEntityDamage(BlightedEntity blighted, LivingEntity en
double remainingHealth = entity.getHealth() - event.getFinalDamage();
if (remainingHealth > 0) {
- Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(), () -> {
- if (entity.isValid() && !entity.isDead()) {
- blighted.updateBossBar();
- blighted.evaluatePhases(entity.getHealth());
- }
- }, 1L);
+ Bukkit.getScheduler()
+ .runTaskLater(
+ BlightedSMP.getInstance(),
+ () -> {
+ if (entity.isValid() && !entity.isDead()) {
+ blighted.updateBossBar();
+ blighted.evaluatePhases(entity.getHealth());
+ }
+ },
+ 1L);
return;
}
blighted.killAllAttachments();
@@ -326,9 +326,7 @@ public void onEntityDeath(EntityDeathEvent event) {
blighted.cleanup();
- BlightedPlayer killer = dead.getKiller() != null
- ? BlightedPlayer.get(dead.getKiller())
- : null;
+ BlightedPlayer killer = dead.getKiller() != null ? BlightedPlayer.get(dead.getKiller()) : null;
blighted.dropLoot(dead.getLocation(), killer);
blighted.onDeath(dead.getLocation());
@@ -339,9 +337,7 @@ public void onEntityDeath(EntityDeathEvent event) {
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
- Bukkit.getScheduler().runTaskLater(
- BlightedSMP.getInstance(), () -> rehydrateChunk(event.getChunk()), 1L
- );
+ Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(), () -> rehydrateChunk(event.getChunk()), 1L);
}
public static Collection getActiveEntities() {
From 5f833493a0d49e461863b0be20a46536fc2c57b0 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 20:44:43 +0200
Subject: [PATCH 20/31] refactor(project): improve formatting, imports, and
style consistency across modules
---
.../engine/entities/EntityManager.java | 7 +-
.../components/impl/ShieldComponent.java | 26 ++++--
.../engine/entities/defense/DamageType.java | 24 ++++--
.../entities/defense/EntityDefenses.java | 6 +-
.../entities/defense/EntityResistance.java | 6 +-
.../listeners/EntityComponentListener.java | 3 +-
.../entities/registry/EntitiesRegistry.java | 12 ++-
.../registry/SpawnableEntitiesRegistry.java | 4 +-
.../entities/rituals/AncientCreature.java | 9 +--
.../entities/rituals/AncientRitual.java | 8 +-
.../entities/rituals/RitualAnimations.java | 8 +-
.../rituals/menu/AncientRitualsMenu.java | 6 +-
.../rituals/menu/RitualAltarMenu.java | 24 +++---
.../entities/spawnable/SpawnableEntity.java | 52 +++++++++---
.../spawnable/condition/SpawnRules.java | 6 +-
.../spawnable/engine/SpawnEvaluator.java | 7 +-
.../engine/fishing/FishingLootTable.java | 9 +--
.../engine/items/BlightedItem.java | 24 +++---
.../blightedSMP/engine/items/ItemType.java | 7 --
.../items/blocks/BlightedBlockListener.java | 2 +-
.../crafting/builder/ShapedRecipeBuilder.java | 80 ++++++++++++++-----
.../builder/ShapelessRecipeBuilder.java | 40 +++++++++-
.../items/registry/menu/ItemRegistryMenu.java | 1 +
.../engine/loot/results/EntityResult.java | 6 +-
.../engine/loot/results/gems/GemsItem.java | 11 +++
.../LootingAwareProbabilisticStrategy.java | 2 +-
.../engine/player/hud/PlayerHudManager.java | 2 -
.../blightedSMP/server/BlightedServer.java | 2 +-
.../blightedSMP/server/PluginFiles.java | 2 +-
.../blightedSMP/server/PluginSettings.java | 4 +-
30 files changed, 261 insertions(+), 139 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityManager.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityManager.java
index a7cad7f7..d6760754 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityManager.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/EntityManager.java
@@ -35,7 +35,7 @@ private EntityManager() {
}
/**
- * Initializes background orphan entity cleanup task.
+ * Initializes a background orphan entity cleanup task.
*/
public static void initialize() {
Bukkit.getScheduler().runTaskTimer(
@@ -62,7 +62,7 @@ public static void sweepOrphanedEntities() {
}
/**
- * Registers active entity instance with its runtime wrapper.
+ * Registers an active entity instance with its runtime wrapper.
*
* @param entity living entity to track
* @param blighted blighted entity wrapper instance
@@ -246,7 +246,8 @@ public static void rehydrateChunk(Chunk chunk) {
boolean syncYaw = yawByte == null || yawByte == 1;
boolean syncPitch = pitchByte != null && pitchByte == 1;
- owner.attachments.removeIf(a -> a.entity() != null && a.entity().getUniqueId().equals(entity.getUniqueId()));
+ owner.attachments.removeIf(attachment -> attachment.entity() != null
+ && attachment.entity().getUniqueId().equals(entity.getUniqueId()));
owner.attachments.add(new EntityAttachment(entity, role, offset, syncYaw, syncPitch));
registerAttachment(entity, owner);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/components/impl/ShieldComponent.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/components/impl/ShieldComponent.java
index 85ea2779..2a6e36bb 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/components/impl/ShieldComponent.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/components/impl/ShieldComponent.java
@@ -16,7 +16,7 @@
/**
* Directional blocking shield component for entities, blocking frontal attacks unless jump-crit.
*/
-public class ShieldComponent implements EntityComponent {
+public final class ShieldComponent implements EntityComponent {
private final double arcDegrees;
private long disableUntil = 0;
@@ -51,11 +51,14 @@ public void onDamageTaken(BlightedEntity owner, EntityDamageByEntityEvent event)
Entity defender = event.getEntity();
Entity damager = event.getDamager();
- Entity source = (damager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter) ? shooter : damager;
+ Entity source = (damager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter)
+ ? shooter
+ : damager;
Location location = defender.getLocation().add(0, 1.8, 0);
if (source instanceof Player player && isAttackBlocked(defender, source)) {
- if (player.getLocation().getY() > player.getLocation().getBlockY() || player.getVelocity().getY() > 0.5) {
+ if (player.getLocation().getY() > player.getLocation().getBlockY()
+ || player.getVelocity().getY() > 0.5) {
disable(5000L);
defender.getWorld().spawnParticle(Particle.EXPLOSION, location, 1, 0, 0, 0, 0);
defender.getWorld().spawnParticle(Particle.WITCH, location, 30, 0.5, 0.5, 0.5, 0.1);
@@ -67,7 +70,16 @@ public void onDamageTaken(BlightedEntity owner, EntityDamageByEntityEvent event)
if (isAttackBlocked(defender, source)) {
event.setCancelled(true);
defender.getWorld().spawnParticle(Particle.SWEEP_ATTACK, location, 1, 0, 0, 0, 0);
- defender.getWorld().spawnParticle(Particle.BLOCK_CRUMBLE, location, 20, 0.2, 0.2, 0.2, 0.1, Material.IRON_BLOCK.createBlockData());
+ defender.getWorld()
+ .spawnParticle(
+ Particle.BLOCK_CRUMBLE,
+ location,
+ 20,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.1,
+ Material.IRON_BLOCK.createBlockData());
defender.getWorld().playSound(location, Sound.ITEM_SHIELD_BLOCK, 1.0f, 1.2f);
}
}
@@ -86,8 +98,10 @@ public boolean isAttackBlocked(Entity defender, Entity attacker) {
Location attackerLocation = attacker.getLocation();
Vector defenderDirection = defenderLocation.getDirection();
- Vector attackerDirection = attackerLocation.toVector()
- .subtract(defenderLocation.toVector()).normalize();
+ Vector attackerDirection = attackerLocation
+ .toVector()
+ .subtract(defenderLocation.toVector())
+ .normalize();
double dotProduct = defenderDirection.dot(attackerDirection);
double angle = Math.toDegrees(Math.acos(dotProduct));
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/DamageType.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/DamageType.java
index 43f2a620..9f7a707f 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/DamageType.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/DamageType.java
@@ -11,7 +11,9 @@
*/
public enum DamageType implements EntityImmunity {
- /** Immunity to fire, lava, fire tick, and campfire damage. */
+ /**
+ * Immunity to fire, lava, fire tick, and campfire damage.
+ */
FIRE {
@Override
public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
@@ -22,7 +24,9 @@ public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
}
},
- /** Immunity to direct melee and sweep attacks. */
+ /**
+ * Immunity to direct melee and sweep attacks.
+ */
MELEE {
@Override
public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
@@ -31,7 +35,9 @@ public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
}
},
- /** Immunity to ranged projectile damage. */
+ /**
+ * Immunity to ranged projectile damage.
+ */
PROJECTILE {
@Override
public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
@@ -39,7 +45,9 @@ public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
}
},
- /** Immunity to fall damage. */
+ /**
+ * Immunity to fall damage.
+ */
FALL {
@Override
public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
@@ -47,7 +55,9 @@ public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
}
},
- /** Immunity to heavy mace weapon attacks. */
+ /**
+ * Immunity to heavy mace weapon attacks.
+ */
MACE {
@Override
public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
@@ -62,7 +72,9 @@ public String getImmunityMessage() {
}
},
- /** Immunity to magic, poison, wither, dragon breath, and sonic boom damage. */
+ /**
+ * Immunity to magic, poison, wither, dragon breath, and sonic boom damage.
+ */
MAGIC {
@Override
public boolean isImmune(LivingEntity livingEntity, EntityDamageEvent event) {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityDefenses.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityDefenses.java
index d6a5406c..e935ce86 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityDefenses.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityDefenses.java
@@ -5,11 +5,7 @@
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* Encapsulates damage immunities and type resistance rules for an entity.
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityResistance.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityResistance.java
index 9ab591f8..5f320edc 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityResistance.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/defense/EntityResistance.java
@@ -1,10 +1,6 @@
package fr.moussax.blightedSMP.engine.entities.defense;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
/**
* Declares a single damage type resistance percentage for an entity.
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/EntityComponentListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/EntityComponentListener.java
index 758a1e90..b01f6f17 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/EntityComponentListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/EntityComponentListener.java
@@ -17,7 +17,8 @@ public final class EntityComponentListener implements Listener {
public void onEntityDamage(EntityDamageByEntityEvent event) {
Entity victim = event.getEntity();
Entity rawDamager = event.getDamager();
- Entity source = (rawDamager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter)
+ Entity source = (rawDamager instanceof Projectile projectile
+ && projectile.getShooter() instanceof Entity shooter)
? shooter
: rawDamager;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java
index 90a1e1f3..e0e93b1c 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/EntitiesRegistry.java
@@ -74,7 +74,7 @@ public static BlightedEntity get(String entityId) {
}
/**
- * Retrieves cloned instance of registered spawnable entity prototype by ID.
+ * Retrieves a cloned instance of a registered spawnable entity prototype by ID.
*
* @param entityId target entity identifier
* @return cloned spawnable entity instance, or {@code null} if untracked or not spawnable
@@ -89,25 +89,23 @@ public static SpawnableEntity getSpawnable(String entityId) {
}
/**
- * Returns list of cloned instances of all registered entity prototypes.
+ * Returns a list of cloned instances of all registered entity prototypes.
*
* @return list of cloned entity prototypes
*/
public static List getAll() {
- return REGISTRY.getAll().stream()
- .map(BlightedEntity::clone)
- .toList();
+ return REGISTRY.getAll().stream().map(BlightedEntity::clone).toList();
}
/**
- * Returns list of cloned instances of all registered spawnable entity prototypes.
+ * Returns a list of cloned instances of all registered spawnable entity prototypes.
*
* @return list of cloned spawnable entity prototypes
*/
public static List getSpawnables() {
return REGISTRY.getAll().stream()
.filter(SpawnableEntity.class::isInstance)
- .map(e -> ((SpawnableEntity) e).clone())
+ .map(entity -> ((SpawnableEntity) entity).clone())
.toList();
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java
index 2ad6dd1d..7b53859a 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/registry/SpawnableEntitiesRegistry.java
@@ -14,7 +14,7 @@ private SpawnableEntitiesRegistry() {
}
/**
- * Retrieves cloned instance of registered spawnable entity prototype by ID.
+ * Retrieves a cloned instance of a registered spawnable entity prototype by ID.
*
* @param entityId target entity identifier
* @return cloned spawnable entity instance, or {@code null} if untracked or not spawnable
@@ -25,7 +25,7 @@ public static SpawnableEntity get(String entityId) {
}
/**
- * Returns list of cloned instances of all registered spawnable entity prototypes.
+ * Returns a list of cloned instances of all registered spawnable entity prototypes.
*
* @return list of cloned spawnable entity prototypes
*/
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientCreature.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientCreature.java
index 7ee2f74b..28ab4e4d 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientCreature.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientCreature.java
@@ -1,22 +1,17 @@
package fr.moussax.blightedSMP.engine.entities.rituals;
+import fr.moussax.bedrock.text.Formatter;
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.content.sound.BlightedSounds;
import fr.moussax.blightedSMP.engine.entities.BlightedEntity;
import fr.moussax.blightedSMP.engine.entities.attachment.AttachmentRole;
-import fr.moussax.bedrock.text.Formatter;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
-import org.bukkit.entity.Display;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.TextDisplay;
+import org.bukkit.entity.*;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.util.Transformation;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientRitual.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientRitual.java
index 3497407f..ecd8cf0c 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientRitual.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/AncientRitual.java
@@ -1,9 +1,9 @@
package fr.moussax.blightedSMP.engine.entities.rituals;
+import fr.moussax.bedrock.utils.ItemBuilder;
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.recipes.CraftingObject;
import fr.moussax.blightedSMP.engine.items.registry.ItemRegistry;
-import fr.moussax.bedrock.utils.ItemBuilder;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@@ -76,7 +76,7 @@ public static Builder of(AncientCreature creature) {
/**
* Configures the item displayed for this ritual.
*
- * @param material base material of the displayed item
+ * @param material base material of the displayed item
* @param configure configuration applied to the item builder
* @return this builder
*/
@@ -105,7 +105,7 @@ public Builder addOffering(CraftingObject offering) {
* Adds a vanilla material as a required offering.
*
* @param material required material
- * @param amount required amount
+ * @param amount required amount
* @return this builder
*/
public Builder addOffering(Material material, int amount) {
@@ -115,7 +115,7 @@ public Builder addOffering(Material material, int amount) {
/**
* Adds a custom item as a required offering.
*
- * @param item required custom item
+ * @param item required custom item
* @param amount required amount
* @return this builder
*/
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/RitualAnimations.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/RitualAnimations.java
index 3eef01ab..1e5fc61d 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/RitualAnimations.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/RitualAnimations.java
@@ -169,11 +169,11 @@ private static void drawVoidVortexAndImplosion(Location location, int tick) {
double z = radius * Math.sin(angle);
double y = Math.sin((tick + i) * 0.4) * 0.8;
- Location particleLoc = center.clone().add(x, y, z);
- Vector inward = center.toVector().subtract(particleLoc.toVector()).normalize().multiply(0.25);
+ Location particleLocation = center.clone().add(x, y, z);
+ Vector inward = center.toVector().subtract(particleLocation.toVector()).normalize().multiply(0.25);
- world.spawnParticle(Particle.PORTAL, particleLoc, 0, inward.getX(), inward.getY(), inward.getZ(), 0.8);
- world.spawnParticle(Particle.SOUL_FIRE_FLAME, particleLoc, 0, inward.getX(), inward.getY(), inward.getZ(), 0.05);
+ world.spawnParticle(Particle.PORTAL, particleLocation, 0, inward.getX(), inward.getY(), inward.getZ(), 0.8);
+ world.spawnParticle(Particle.SOUL_FIRE_FLAME, particleLocation, 0, inward.getX(), inward.getY(), inward.getZ(), 0.05);
}
world.spawnParticle(Particle.REVERSE_PORTAL, center, 4, 0.1, 0.1, 0.1, 0.08);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/AncientRitualsMenu.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/AncientRitualsMenu.java
index d26e335f..a270b937 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/AncientRitualsMenu.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/AncientRitualsMenu.java
@@ -1,13 +1,13 @@
package fr.moussax.blightedSMP.engine.entities.rituals.menu;
-import fr.moussax.blightedSMP.engine.entities.rituals.AncientRitual;
-import fr.moussax.blightedSMP.engine.entities.rituals.registry.RitualRegistry;
-import fr.moussax.blightedSMP.engine.items.recipes.CraftingObject;
import fr.moussax.bedrock.text.Formatter;
import fr.moussax.bedrock.ui.menu.Menu;
import fr.moussax.bedrock.ui.menu.interaction.MenuElementPreset;
import fr.moussax.bedrock.ui.menu.interaction.MenuItemInteraction;
import fr.moussax.bedrock.utils.ItemBuilder;
+import fr.moussax.blightedSMP.engine.entities.rituals.AncientRitual;
+import fr.moussax.blightedSMP.engine.entities.rituals.registry.RitualRegistry;
+import fr.moussax.blightedSMP.engine.items.recipes.CraftingObject;
import fr.moussax.blightedSMP.utils.Utilities;
import org.bukkit.ChatColor;
import org.bukkit.Material;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/RitualAltarMenu.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/RitualAltarMenu.java
index 68d0b02b..92800c24 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/RitualAltarMenu.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/rituals/menu/RitualAltarMenu.java
@@ -1,24 +1,24 @@
package fr.moussax.blightedSMP.engine.entities.rituals.menu;
+import fr.moussax.bedrock.text.Formatter;
+import fr.moussax.bedrock.text.Messenger;
+import fr.moussax.bedrock.ui.menu.Menu;
+import fr.moussax.bedrock.ui.menu.TickableMenu;
+import fr.moussax.bedrock.ui.menu.interaction.MenuElementPreset;
+import fr.moussax.bedrock.utils.ItemBuilder;
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.content.sound.BlightedSounds;
import fr.moussax.blightedSMP.engine.entities.rituals.AncientCreature;
import fr.moussax.blightedSMP.engine.entities.rituals.AncientRitual;
import fr.moussax.blightedSMP.engine.entities.rituals.RitualAnimations;
import fr.moussax.blightedSMP.engine.items.recipes.CraftingObject;
-import fr.moussax.bedrock.ui.menu.Menu;
-import fr.moussax.bedrock.ui.menu.interaction.MenuElementPreset;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
-import fr.moussax.bedrock.utils.ItemBuilder;
import fr.moussax.blightedSMP.utils.Utilities;
-import fr.moussax.bedrock.text.Formatter;
-import fr.moussax.bedrock.text.Messenger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
-import fr.moussax.bedrock.ui.menu.TickableMenu;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
@@ -110,7 +110,8 @@ private void setupResultDisplay() {
ItemStack barrier = new ItemBuilder(Material.BARRIER, "§cRitual Required")
.addLore("§7Select an ancient ritual to start", "§7the invocation process.")
.toItemStack();
- setItem(25, barrier, (_, _) -> {});
+ setItem(25, barrier, (_, _) -> {
+ });
return;
}
@@ -123,7 +124,8 @@ private void setupResultDisplay() {
result = builder.toItemStack();
}
- setItem(25, result, (_, _) -> {});
+ setItem(25, result, (_, _) -> {
+ });
}
private void checkRequirements(Player player) {
@@ -166,7 +168,8 @@ private Map aggregateRequirements() {
private void displayRequiredIngredients() {
for (int i = 0; i < ritual.getOfferings().size() && i < GRID_SLOTS.length; i++) {
CraftingObject ingredient = ritual.getOfferings().get(i);
- setItem(GRID_SLOTS[i], createDisplayItem(ingredient), (_, _) -> {});
+ setItem(GRID_SLOTS[i], createDisplayItem(ingredient), (_, _) -> {
+ });
}
}
@@ -199,7 +202,8 @@ private void setupStatusPanes() {
"§7to invoke ancient forgotten entities."
)
.toItemStack();
- setItem(14, shriekerIcon, (_, _) -> {});
+ setItem(14, shriekerIcon, (_, _) -> {
+ });
}
private Material determineIndicatorMaterial() {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/SpawnableEntity.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/SpawnableEntity.java
index d24867d9..d9fd0ae2 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/SpawnableEntity.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/SpawnableEntity.java
@@ -7,7 +7,10 @@
import fr.moussax.blightedSMP.engine.entities.spawnable.condition.SpawnCondition;
import fr.moussax.blightedSMP.engine.entities.spawnable.engine.SpawnMode;
import lombok.Getter;
-import org.bukkit.*;
+import org.bukkit.Location;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Particle;
+import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.persistence.PersistentDataType;
@@ -23,17 +26,23 @@
*/
public abstract class SpawnableEntity extends BlightedEntity {
- /** Persistent data key storing comma-separated active affix IDs assigned to this entity. */
- public static final NamespacedKey AFFIXES_KEY = new NamespacedKey(BlightedSMP.getInstance(), "blighted_active_affix");
+ /**
+ * Persistent data key storing comma-separated active affix IDs assigned to this entity.
+ */
+ public static final NamespacedKey AFFIXES_KEY =
+ new NamespacedKey(BlightedSMP.getInstance(), "blighted_active_affix");
@Getter
private final double spawnProbability;
+
@Getter
private final SpawnMode spawnMode;
+
private SpawnProfile spawnProfile;
@Getter
private double affixChance = 0.0;
+
@Getter
private int maxAffixes = 1;
@@ -65,7 +74,7 @@ public void setMaxAffixes(int maxAffixes) {
* @param entityId unique entity identifier
* @param name display name
* @param maxHealth maximum health
- * @param entityType underlying Minecraft entity type
+ * @param entityType underlying a Minecraft entity type
* @param probability spawn probability in range {@code [0.0, 1.0]}
*/
protected SpawnableEntity(String entityId, String name, int maxHealth, EntityType entityType, double probability) {
@@ -78,11 +87,12 @@ protected SpawnableEntity(String entityId, String name, int maxHealth, EntityTyp
* @param entityId unique entity identifier
* @param name display name
* @param maxHealth maximum health
- * @param entityType underlying Minecraft entity type
+ * @param entityType underlying a Minecraft entity type
* @param probability spawn probability in range {@code [0.0, 1.0]}
* @param mode spawn mode
*/
- protected SpawnableEntity(String entityId, String name, int maxHealth, EntityType entityType, double probability, SpawnMode mode) {
+ protected SpawnableEntity(
+ String entityId, String name, int maxHealth, EntityType entityType, double probability, SpawnMode mode) {
this(entityId, name, maxHealth, 1, 0, entityType, probability, mode);
}
@@ -93,11 +103,18 @@ protected SpawnableEntity(String entityId, String name, int maxHealth, EntityTyp
* @param name display name
* @param maxHealth maximum health
* @param damage base attack damage
- * @param entityType underlying Minecraft entity type
+ * @param entityType underlying a Minecraft entity type
* @param probability spawn probability in range {@code [0.0, 1.0]}
* @param mode spawn mode
*/
- protected SpawnableEntity(String entityId, String name, int maxHealth, int damage, EntityType entityType, double probability, SpawnMode mode) {
+ protected SpawnableEntity(
+ String entityId,
+ String name,
+ int maxHealth,
+ int damage,
+ EntityType entityType,
+ double probability,
+ SpawnMode mode) {
this(entityId, name, maxHealth, damage, 0, entityType, probability, mode);
}
@@ -109,12 +126,20 @@ protected SpawnableEntity(String entityId, String name, int maxHealth, int damag
* @param maxHealth maximum health
* @param damage base attack damage
* @param defense base armor defense
- * @param entityType underlying Minecraft entity type
+ * @param entityType underlying a Minecraft entity type
* @param probability spawn probability in range {@code [0.0, 1.0]}
* @param mode spawn mode
* @throws IllegalArgumentException if {@code probability} is outside {@code [0.0, 1.0]}
*/
- protected SpawnableEntity(String entityId, String name, int maxHealth, int damage, int defense, EntityType entityType, double probability, SpawnMode mode) {
+ protected SpawnableEntity(
+ String entityId,
+ String name,
+ int maxHealth,
+ int damage,
+ int defense,
+ EntityType entityType,
+ double probability,
+ SpawnMode mode) {
super(name, maxHealth, damage, defense, entityType);
if (probability < 0.0 || probability > 1.0) {
throw new IllegalArgumentException("spawnProbability must be in [0.0, 1.0], got: " + probability);
@@ -146,7 +171,8 @@ public LivingEntity spawn(Location location) {
applyAffix(affix);
}
- spawned.getPersistentDataContainer().set(AFFIXES_KEY, PersistentDataType.STRING, String.join(",", affixIds));
+ spawned.getPersistentDataContainer()
+ .set(AFFIXES_KEY, PersistentDataType.STRING, String.join(",", affixIds));
}
}
@@ -197,9 +223,9 @@ private void startEliteAura() {
double angle = time * 0.2;
double x = Math.cos(angle) * 0.6;
double z = Math.sin(angle) * 0.6;
- Location orbitLoc = center.clone().add(x, 0, z);
+ Location orbitLocation = center.clone().add(x, 0, z);
- world.spawnParticle(Particle.SCULK_SOUL, orbitLoc, 1, 0.05, 0.05, 0.05, 0.02);
+ world.spawnParticle(Particle.SCULK_SOUL, orbitLocation, 1, 0.05, 0.05, 0.05, 0.02);
if (time % 10 == 0) {
world.spawnParticle(Particle.ENCHANT, center, 5, 0.5, 0.5, 0.5, 0.01);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/condition/SpawnRules.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/condition/SpawnRules.java
index 4918e4eb..135bc790 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/condition/SpawnRules.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/condition/SpawnRules.java
@@ -219,7 +219,7 @@ public static SpawnCondition nearActiveTrialSpawner(int radius) {
if (block.getType() != Material.TRIAL_SPAWNER) continue;
if (block.getBlockData() instanceof TrialSpawner trialData
- && trialData.getTrialSpawnerState() == State.ACTIVE) {
+ && trialData.getTrialSpawnerState() == State.ACTIVE) {
return true;
}
}
@@ -248,8 +248,8 @@ public static SpawnCondition nearOminousTrialSpawner(int radius) {
if (block.getType() != Material.TRIAL_SPAWNER) continue;
if (block.getBlockData() instanceof TrialSpawner trialData
- && trialData.isOminous()
- && trialData.getTrialSpawnerState() == State.ACTIVE) {
+ && trialData.isOminous()
+ && trialData.getTrialSpawnerState() == State.ACTIVE) {
return true;
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java
index 8f8eff20..5e022d3e 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/spawnable/engine/SpawnEvaluator.java
@@ -14,16 +14,17 @@
*/
public final class SpawnEvaluator {
- private SpawnEvaluator() {}
+ private SpawnEvaluator() {
+ }
/**
- * Evaluates a list of candidate entities against a target location and selects an eligible entity weighted by probability.
+ * Evaluates spawn conditions for candidate entities and selects an eligible entity weighted by probability.
*
* @param candidates candidate spawnable entity prototypes
* @param location target spawn location
* @param world target world
* @param random random number generator
- * @return selected entity definition, or {@code null} if no spawn condition was met or the roll failed
+ * @return selected entity prototype, or {@code null} if no spawn condition was met or probability roll failed
*/
@Nullable
public static SpawnableEntity selectCandidate(List candidates, Location location, World world, ThreadLocalRandom random) {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingLootTable.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingLootTable.java
index ea90daef..c9a0ec68 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingLootTable.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingLootTable.java
@@ -116,12 +116,9 @@ public static Builder builder() {
*/
public static final class Builder {
private static final Function FISHING_FEEDBACK_MAPPER = quality -> switch (quality) {
- case GOOD_CATCH ->
- FeedbackSpecification.full(" §5§lGOOD CATCH! §f| §7You found §f", Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 2.0f);
- case GREAT_CATCH ->
- FeedbackSpecification.full(" §6§lGREAT CATCH! §f| §7You found §f", Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.5f);
- case OUTSTANDING_CATCH ->
- FeedbackSpecification.full(" §d§lOUTSTANDING CATCH! §f| §7You found §f", Sound.ENTITY_PLAYER_LEVELUP, 1.5f);
+ case GOOD_CATCH -> FeedbackSpecification.full(" §5§lGOOD CATCH! §f| §7You found §f", Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 2.0f);
+ case GREAT_CATCH -> FeedbackSpecification.full(" §6§lGREAT CATCH! §f| §7You found §f", Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.5f);
+ case OUTSTANDING_CATCH -> FeedbackSpecification.full(" §d§lOUTSTANDING CATCH! §f| §7You found §f", Sound.ENTITY_PLAYER_LEVELUP, 1.5f);
default -> null;
};
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/BlightedItem.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/BlightedItem.java
index 8770f1f8..1b1894e9 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/BlightedItem.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/BlightedItem.java
@@ -1,16 +1,16 @@
package fr.moussax.blightedSMP.engine.items;
+import fr.moussax.bedrock.ui.menu.Menu;
+import fr.moussax.bedrock.utils.ItemBuilder;
import fr.moussax.blightedSMP.BlightedSMP;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityExecutor;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
import fr.moussax.blightedSMP.engine.items.abilities.FullSetBonus;
import fr.moussax.blightedSMP.engine.items.recipes.RecipePreviewManager;
import fr.moussax.blightedSMP.engine.items.registry.ItemRegistry;
import fr.moussax.blightedSMP.engine.items.rules.ItemRule;
import fr.moussax.blightedSMP.engine.items.rules.ItemRuleEngine;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
-import fr.moussax.bedrock.ui.menu.Menu;
-import fr.moussax.bedrock.utils.ItemBuilder;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@@ -52,7 +52,7 @@ public final class BlightedItem extends ItemBuilder implements ItemRule, Supplie
@Getter
private FullSetBonus fullSetBonus;
@Getter
- private final List abilities = new ArrayList<>();
+ private final List> abilities = new ArrayList<>();
@Getter
private final ItemRuleEngine ruleEngine = new ItemRuleEngine();
@Getter
@@ -93,7 +93,7 @@ public BlightedItem(@NonNull String itemId, @NonNull ItemType type, @NonNull Ite
*
* @param ability ability to add
*/
- public void addAbility(Ability ability) {
+ public void addAbility(AbilityManager extends Event> ability) {
addAbility(ability, true);
}
@@ -103,7 +103,7 @@ public void addAbility(Ability ability) {
* @param ability ability to add
* @param injectLore {@code true} to append formatted ability description to lore
*/
- public void addAbility(Ability ability, boolean injectLore) {
+ public void addAbility(AbilityManager extends Event> ability, boolean injectLore) {
if (ability == null) return;
this.abilities.add(ability);
@@ -118,8 +118,9 @@ public void addAbility(Ability ability, boolean injectLore) {
*
* @param abilities abilities to add
*/
- public void addAbilities(Ability... abilities) {
- for (Ability ability : abilities) {
+ @SafeVarargs
+ public final void addAbilities(AbilityManager extends Event>... abilities) {
+ for (AbilityManager extends Event> ability : abilities) {
addAbility(ability, true);
}
}
@@ -224,10 +225,11 @@ public static BlightedItem fromItemStack(@NonNull ItemStack itemStack) {
* @param blightedPlayer player context executing the ability
* @param event triggering event
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
public void triggerAbilities(BlightedPlayer blightedPlayer, Event event) {
- for (Ability ability : abilities) {
- if (ability.type().matches(event)) {
- AbilityExecutor.execute(ability, blightedPlayer, event);
+ for (AbilityManager extends Event> ability : abilities) {
+ if (ability.getType().matches(event)) {
+ AbilityExecutor.execute((AbilityManager) ability, blightedPlayer, event);
}
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/ItemType.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/ItemType.java
index bb96ae60..ecb7a5d5 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/ItemType.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/ItemType.java
@@ -69,19 +69,12 @@ public enum ItemType {
* Broad grouping for item types used in inventory filtering and display categories.
*/
public enum Category {
- /** Armor equipment category. */
ARMOR,
- /** Melee weapon category. */
MELEE_WEAPON,
- /** Ranged weapon category. */
RANGE_WEAPON,
- /** Tool and utility item category. */
TOOLS,
- /** Placeable block category. */
BLOCKS,
- /** Material and resource category. */
MATERIAL,
- /** Miscellaneous item category. */
MISCELLANEOUS
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
index 195071f6..7b1a8851 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
@@ -191,4 +191,4 @@ private void cleanupBlockData(Block block) {
private void cacheMetadata(Block block, String id) {
block.setMetadata("blighted_id", new FixedMetadataValue(plugin, id));
}
-}
\ No newline at end of file
+}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java
index 219b142e..f9391616 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java
@@ -1,11 +1,15 @@
package fr.moussax.blightedSMP.engine.items.recipes.crafting.builder;
import fr.moussax.blightedSMP.engine.items.BlightedItem;
+import fr.moussax.blightedSMP.engine.items.recipes.CraftingObject;
import fr.moussax.blightedSMP.engine.items.recipes.crafting.BlightedShapedRecipe;
import fr.moussax.blightedSMP.engine.items.recipes.ShapeEncoder;
import fr.moussax.blightedSMP.engine.items.registry.ItemRegistry;
import org.bukkit.Material;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Fluent builder for creating {@link BlightedShapedRecipe} instances.
*
@@ -17,7 +21,10 @@ public final class ShapedRecipeBuilder {
private final BlightedItem result;
private final int amount;
- private ShapeEncoder encoder;
+ private String line1;
+ private String line2;
+ private String line3;
+ private final Map bindings = new HashMap<>();
private int attributeSourceSlot = -1;
private ShapedRecipeBuilder(BlightedItem result, int amount) {
@@ -46,7 +53,7 @@ public static ShapedRecipeBuilder of(BlightedItem result, int amount) {
* @throws IllegalArgumentException if the item ID is not registered
*/
public static ShapedRecipeBuilder of(String resultId, int amount) {
- return new ShapedRecipeBuilder(ItemRegistry.getItem(resultId), amount);
+ return new ShapedRecipeBuilder(ItemRegistry.get(resultId), amount);
}
/**
@@ -58,10 +65,24 @@ public static ShapedRecipeBuilder of(String resultId, int amount) {
* @return this builder
*/
public ShapedRecipeBuilder shape(String line1, String line2, String line3) {
- this.encoder = new ShapeEncoder(line1, line2, line3);
+ this.line1 = line1;
+ this.line2 = line2;
+ this.line3 = line3;
return this;
}
+ /**
+ * Binds a crafting shape character to a single material ingredient.
+ *
+ * @param key the character used in the recipe shape
+ * @param material the material represented by the character
+ * @return this builder
+ */
+ // ponytail: simplified — single-item quantity default overload
+ public ShapedRecipeBuilder bind(char key, Material material) {
+ return bind(key, material, 1);
+ }
+
/**
* Binds a crafting shape character to a material.
*
@@ -69,15 +90,24 @@ public ShapedRecipeBuilder shape(String line1, String line2, String line3) {
* @param material the material represented by the character
* @param amount the required amount of the material
* @return this builder
- * @throws IllegalStateException if {@link #shape(String, String, String)}
- * has not been called
*/
public ShapedRecipeBuilder bind(char key, Material material, int amount) {
- validateEncoder();
- encoder.bindKey(key, material, amount);
+ bindings.put(key, new CraftingObject(material, amount));
return this;
}
+ /**
+ * Binds a crafting shape character to a single custom item ingredient.
+ *
+ * @param key the character used in the recipe shape
+ * @param item the custom item represented by the character
+ * @return this builder
+ */
+ // ponytail: simplified — single-item quantity default overload
+ public ShapedRecipeBuilder bind(char key, BlightedItem item) {
+ return bind(key, item, 1);
+ }
+
/**
* Binds a crafting shape character to a custom item.
*
@@ -85,15 +115,25 @@ public ShapedRecipeBuilder bind(char key, Material material, int amount) {
* @param item the custom item represented by the character
* @param amount the required amount of the item
* @return this builder
- * @throws IllegalStateException if {@link #shape(String, String, String)}
- * has not been called
*/
public ShapedRecipeBuilder bind(char key, BlightedItem item, int amount) {
- validateEncoder();
- encoder.bindKey(key, item, amount);
+ bindings.put(key, new CraftingObject(item, amount));
return this;
}
+ /**
+ * Binds a crafting shape character to a single registered custom item ingredient.
+ *
+ * @param key the character used in the recipe shape
+ * @param itemId the ID of the custom item represented by the character
+ * @return this builder
+ * @throws IllegalArgumentException if the item ID is not registered
+ */
+ // ponytail: simplified — single-item quantity default overload
+ public ShapedRecipeBuilder bind(char key, String itemId) {
+ return bind(key, itemId, 1);
+ }
+
/**
* Binds a crafting shape character to a registered custom item.
*
@@ -102,11 +142,9 @@ public ShapedRecipeBuilder bind(char key, BlightedItem item, int amount) {
* @param amount the required amount of the item
* @return this builder
* @throws IllegalArgumentException if the item ID is not registered
- * @throws IllegalStateException if {@link #shape(String, String, String)}
- * has not been called
*/
public ShapedRecipeBuilder bind(char key, String itemId, int amount) {
- return bind(key, ItemRegistry.getItem(itemId), amount);
+ return bind(key, ItemRegistry.get(itemId), amount);
}
/**
@@ -137,8 +175,14 @@ public ShapedRecipeBuilder attributeSource(int slotIndex) {
* @return the constructed shaped recipe
* @throws IllegalStateException if the recipe shape has not been defined
*/
+ // ponytail: simplified — order-independent shape and key binding resolution upon build
public BlightedShapedRecipe build() {
- validateEncoder();
+ if (line1 == null || line2 == null || line3 == null) {
+ throw new IllegalStateException("Recipe shape has not been defined yet. Call .shape() first.");
+ }
+ ShapeEncoder encoder = new ShapeEncoder(line1, line2, line3);
+ bindings.forEach(encoder::bindKey);
+
BlightedShapedRecipe recipe = new BlightedShapedRecipe(result, amount);
recipe.setRecipe(encoder.encodeCraftingRecipe());
@@ -148,10 +192,4 @@ public BlightedShapedRecipe build() {
return recipe;
}
-
- private void validateEncoder() {
- if (encoder == null) {
- throw new IllegalStateException("Recipe shape has not been defined yet. Call .shape() first.");
- }
- }
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
index de8a4f33..b9601aa6 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
@@ -45,7 +45,18 @@ public static ShapelessRecipeBuilder of(BlightedItem result) {
* @throws IllegalArgumentException if the item ID is not registered
*/
public static ShapelessRecipeBuilder of(String resultId) {
- return new ShapelessRecipeBuilder(ItemRegistry.getItem(resultId));
+ return new ShapelessRecipeBuilder(ItemRegistry.get(resultId));
+ }
+
+ /**
+ * Adds a single material ingredient to the recipe.
+ *
+ * @param material the material required by the recipe
+ * @return this builder
+ */
+ // ponytail: simplified — single-item quantity default overload
+ public ShapelessRecipeBuilder addIngredient(Material material) {
+ return addIngredient(material, 1, false);
}
/**
@@ -80,6 +91,17 @@ public ShapelessRecipeBuilder addIngredient(
return this;
}
+ /**
+ * Adds a single custom item ingredient to the recipe.
+ *
+ * @param item the custom item required by the recipe
+ * @return this builder
+ */
+ // ponytail: simplified — single-item quantity default overload
+ public ShapelessRecipeBuilder addIngredient(BlightedItem item) {
+ return addIngredient(item, 1, false);
+ }
+
/**
* Adds a custom item ingredient to the recipe.
*
@@ -112,6 +134,18 @@ public ShapelessRecipeBuilder addIngredient(
return this;
}
+ /**
+ * Adds a single registered custom item as an ingredient.
+ *
+ * @param itemId the ID of the required custom item
+ * @return this builder
+ * @throws IllegalArgumentException if the item ID is not registered
+ */
+ // ponytail: simplified — single-item quantity default overload
+ public ShapelessRecipeBuilder addIngredient(String itemId) {
+ return addIngredient(ItemRegistry.get(itemId), 1, false);
+ }
+
/**
* Adds a registered custom item as an ingredient.
*
@@ -121,7 +155,7 @@ public ShapelessRecipeBuilder addIngredient(
* @throws IllegalArgumentException if the item ID is not registered
*/
public ShapelessRecipeBuilder addIngredient(String itemId, int amount) {
- return addIngredient(ItemRegistry.getItem(itemId), amount, false);
+ return addIngredient(ItemRegistry.get(itemId), amount, false);
}
/**
@@ -140,7 +174,7 @@ public ShapelessRecipeBuilder addIngredient(
int amount,
boolean isAttributeSource
) {
- return addIngredient(ItemRegistry.getItem(itemId), amount, isAttributeSource);
+ return addIngredient(ItemRegistry.get(itemId), amount, isAttributeSource);
}
/**
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/registry/menu/ItemRegistryMenu.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/registry/menu/ItemRegistryMenu.java
index 10a810a0..297839e2 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/registry/menu/ItemRegistryMenu.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/registry/menu/ItemRegistryMenu.java
@@ -23,6 +23,7 @@
import java.util.function.Predicate;
public final class ItemRegistryMenu {
+
private static final int[] CATEGORY_SLOTS = PaginatedMenu.INNER_GRID_SLOTS;
private static final int SEARCH_SLOT = 41;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/EntityResult.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/EntityResult.java
index 2fba1dcd..e746321d 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/EntityResult.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/EntityResult.java
@@ -20,7 +20,11 @@ public final class EntityResult implements LootResult {
private final Function customSpawner;
private final Consumer entityModifier;
- private EntityResult(EntityType entityType, Function customSpawner, Consumer entityModifier) {
+ private EntityResult(
+ EntityType entityType,
+ Function customSpawner,
+ Consumer entityModifier
+ ) {
this.entityType = entityType;
this.customSpawner = customSpawner;
this.entityModifier = entityModifier;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/gems/GemsItem.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/gems/GemsItem.java
index 184fa59d..ff9c1b57 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/gems/GemsItem.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/results/gems/GemsItem.java
@@ -4,6 +4,7 @@
import fr.moussax.blightedSMP.content.sound.BlightedSounds;
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.items.registry.ItemRegistry;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import fr.moussax.bedrock.text.Messenger;
@@ -50,6 +51,16 @@ public void addGems(BlightedPlayer player) {
*/
public static class BlightedGemstoneAbility implements AbilityManager {
+ @Override
+ public String getName() {
+ return "Consume Gems";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.RIGHT_CLICK;
+ }
+
@Override
public boolean triggerAbility(PlayerInteractEvent event) {
if (event.getItem() == null) return false;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/strategies/LootingAwareProbabilisticStrategy.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/strategies/LootingAwareProbabilisticStrategy.java
index c8cac85f..ddae5bb5 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/strategies/LootingAwareProbabilisticStrategy.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/loot/strategies/LootingAwareProbabilisticStrategy.java
@@ -59,7 +59,7 @@ public List select(List validEntries, LootContext context)
}
private int extractLootingLevel(LootContext context) {
- if (context.blightedPlayer() == null || context.blightedPlayer().getPlayer() == null) {
+ if (context.blightedPlayer() == null) {
return 0;
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/player/hud/PlayerHudManager.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/player/hud/PlayerHudManager.java
index 671f9203..7818a0d8 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/player/hud/PlayerHudManager.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/player/hud/PlayerHudManager.java
@@ -11,9 +11,7 @@
*/
public final class PlayerHudManager {
- /** Action bar section identifier for player gem balance. */
public static final String SECTION_GEMS = "gems";
- /** Action bar section identifier for player mana pool. */
public static final String SECTION_MANA = "mana";
private final ActionbarService actionBarService;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/BlightedServer.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/BlightedServer.java
index 9e78d017..c06df5aa 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/BlightedServer.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/BlightedServer.java
@@ -48,7 +48,7 @@ public static void rehydrateEntitiesOnLoadedChunks(JavaPlugin plugin) {
final Iterator iterator = chunks.iterator();
final int BATCH_SIZE = 100;
int processedCount = 0;
- long startTime = System.currentTimeMillis();
+ final long startTime = System.currentTimeMillis();
@Override
public void run() {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginFiles.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginFiles.java
index 82da95e2..04c6ff5d 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginFiles.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginFiles.java
@@ -15,7 +15,7 @@ public enum PluginFiles {
/**
* Primary SQLite database file name.
*/
- DATABASE("blighted_database.db");
+ DATABASE("blightedsmp_database.db");
/**
* Relative file name within the plugin data directory.
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginSettings.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginSettings.java
index e9caadf2..6a9d1864 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginSettings.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/server/PluginSettings.java
@@ -1,9 +1,9 @@
package fr.moussax.blightedSMP.server;
-import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.bedrock.utils.debug.Log;
import lombok.Getter;
import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.plugin.java.JavaPlugin;
/**
* Loads and holds runtime configuration settings from {@code config.yml}.
@@ -31,7 +31,7 @@ private PluginSettings() {
* @param plugin plugin instance providing configuration access
* @return loaded settings instance with defensive defaults
*/
- public static PluginSettings load(BlightedSMP plugin) {
+ public static PluginSettings load(JavaPlugin plugin) {
PluginSettings settings = new PluginSettings();
try {
plugin.reloadConfig();
From 486da650c7f1f4cdcd837c0affbb3f1037d8c231 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 21:45:06 +0200
Subject: [PATCH 21/31] feat(entities): add type-safe component lookup and
encapsulate attachments in BlightedEntity
---
.../engine/entities/BlightedEntity.java | 36 ++++++++++++++++---
.../listeners/BlightedEntitiesListener.java | 30 +++++++---------
2 files changed, 45 insertions(+), 21 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
index fb113cde..bd771b66 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
@@ -63,7 +63,7 @@ public abstract class BlightedEntity implements Cloneable {
private LifecycleTaskManager coreTasks = new LifecycleTaskManager();
private LifecycleTaskManager phaseTasks = new LifecycleTaskManager();
private Map components = new HashMap<>();
- public Set attachments = new CopyOnWriteArraySet<>();
+ protected Set attachments = new CopyOnWriteArraySet<>();
private long lastDamageTick = -1L;
private UUID lastDamagerUuid = null;
@@ -699,7 +699,7 @@ public BlockDisplay attachBlockDisplay(Vector offset, Consumer con
}
/**
- * Attaches a multi-part hittable {@link Interaction} hitbox entity.
+ * Attaches a multipart hittable {@link Interaction} hitbox entity.
*
* @param offset local offset relative to base entity origin and facing yaw
* @param width hitbox width
@@ -712,8 +712,8 @@ public Interaction attachHitbox(Vector offset, float width, float height, Consum
return null;
}
Vector localOffset = offset != null ? offset : new Vector(0, 0, 0);
- Location spawnLoc = entity.getLocation().clone().add(localOffset);
- Interaction interaction = entity.getWorld().spawn(spawnLoc, Interaction.class, i -> {
+ Location spawnLocation = entity.getLocation().clone().add(localOffset);
+ Interaction interaction = entity.getWorld().spawn(spawnLocation, Interaction.class, i -> {
i.setInteractionWidth(width);
i.setInteractionHeight(height);
if (configurator != null) {
@@ -962,6 +962,15 @@ public void addComponent(EntityComponent component) {
}
}
+ /**
+ * Returns an unmodifiable view of active entity attachments.
+ *
+ * @return active entity attachments
+ */
+ public Set getAttachments() {
+ return Collections.unmodifiableSet(attachments);
+ }
+
/**
* Returns a registered component by identifier.
*
@@ -974,6 +983,25 @@ public T getComponent(String id) {
return (T) components.get(id);
}
+ /**
+ * Returns the first registered component matching the specified class type.
+ *
+ * @param componentClass expected component class type
+ * @param expected component type
+ * @return matching component instance, or {@code null} if not registered
+ */
+ public T getComponent(Class componentClass) {
+ if (componentClass == null) {
+ return null;
+ }
+ for (EntityComponent component : components.values()) {
+ if (componentClass.isInstance(component)) {
+ return componentClass.cast(component);
+ }
+ }
+ return null;
+ }
+
/**
* Returns a snapshot of all registered components.
*
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
index fb99b785..bbe25ea9 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/listeners/BlightedEntitiesListener.java
@@ -138,8 +138,8 @@ private AttachmentRole getAttachmentRole(BlightedEntity owner, Entity attachment
return AttachmentRole.SUBORDINATE;
}
- if (owner != null && owner.attachments != null) {
- for (EntityAttachment attachment : owner.attachments) {
+ if (owner != null) {
+ for (EntityAttachment attachment : owner.getAttachments()) {
if (attachmentEntity.equals(attachment.entity())) {
return attachment.role();
}
@@ -159,10 +159,9 @@ private AttachmentRole getAttachmentRole(BlightedEntity owner, Entity attachment
private void handleDamageDealt(EntityDamageByEntityEvent event) {
Entity rawDamager = event.getDamager();
- Entity source =
- (rawDamager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter)
- ? shooter
- : rawDamager;
+ Entity source = (rawDamager instanceof Projectile projectile && projectile.getShooter() instanceof Entity shooter)
+ ? shooter
+ : rawDamager;
BlightedEntity damager = getBlightedEntity(source);
if (damager != null) {
@@ -211,16 +210,13 @@ private void handleBlightedEntityDamage(BlightedEntity blighted, LivingEntity en
double remainingHealth = entity.getHealth() - event.getFinalDamage();
if (remainingHealth > 0) {
- Bukkit.getScheduler()
- .runTaskLater(
- BlightedSMP.getInstance(),
- () -> {
- if (entity.isValid() && !entity.isDead()) {
- blighted.updateBossBar();
- blighted.evaluatePhases(entity.getHealth());
- }
- },
- 1L);
+ Bukkit.getScheduler().runTaskLater(BlightedSMP.getInstance(),
+ () -> {
+ if (entity.isValid() && !entity.isDead()) {
+ blighted.updateBossBar();
+ blighted.evaluatePhases(entity.getHealth());
+ }
+ }, 1L);
return;
}
blighted.killAllAttachments();
@@ -237,7 +233,7 @@ private void flashHurtAndCancelKnockback(BlightedEntity owner, Entity hitEntity)
ownerEntity.playHurtAnimation(0.0f);
}
- for (EntityAttachment attachment : owner.attachments) {
+ for (EntityAttachment attachment : owner.getAttachments()) {
if (attachment.role() == AttachmentRole.SUBORDINATE) {
continue;
}
From 68a3f74616220b42ee5deb8e104a8bf8c37210f6 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 22:55:52 +0200
Subject: [PATCH 22/31] fix(recipes): support result amounts in shapeless
recipes and validate result IDs
---
.../engine/fishing/FishingListener.java | 37 +++++++---------
.../items/blocks/BlightedBlockListener.java | 21 +++++-----
.../crafting/BlightedShapelessRecipe.java | 9 +++-
.../crafting/builder/ShapedRecipeBuilder.java | 6 ++-
.../builder/ShapelessRecipeBuilder.java | 42 ++++++++++++++++---
.../crafting/registry/RecipeRegistry.java | 12 +++++-
6 files changed, 85 insertions(+), 42 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingListener.java
index 7c99d6f5..2f440ee8 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/fishing/FishingListener.java
@@ -196,37 +196,30 @@ private void handleStandardFishing(PlayerFishEvent event, Player player, FishHoo
FishingComboTracker.spawnBonusExperience(player.getWorld(), player.getLocation(), newCombo);
}
- private ItemStack findFishingRodItem(Player player, ItemType requiredType) {
+ private ItemStack getHeldFishingRodStack(Player player) {
ItemStack mainHandItem = player.getInventory().getItemInMainHand();
- if (isRodMaterial(mainHandItem)) {
- BlightedItem mainHandBlightedItem = BlightedItem.fromItemStack(mainHandItem);
- if (mainHandBlightedItem != null && mainHandBlightedItem.getItemType() == requiredType) {
- return mainHandItem;
- }
- }
+ if (isRodMaterial(mainHandItem)) return mainHandItem;
ItemStack offhandItem = player.getInventory().getItemInOffHand();
- if (isRodMaterial(offhandItem)) {
- BlightedItem offhandBlightedItem = BlightedItem.fromItemStack(offhandItem);
- if (offhandBlightedItem != null && offhandBlightedItem.getItemType() == requiredType) {
- return offhandItem;
- }
- }
+ if (isRodMaterial(offhandItem)) return offhandItem;
return null;
}
- private int resolveVanillaLuckLevel(Player player) {
- ItemStack mainHandItem = player.getInventory().getItemInMainHand();
- if (isRodMaterial(mainHandItem)) {
- return mainHandItem.getEnchantmentLevel(Enchantment.LUCK_OF_THE_SEA);
+ private ItemStack findFishingRodItem(Player player, ItemType requiredType) {
+ ItemStack rodStack = getHeldFishingRodStack(player);
+ if (rodStack != null) {
+ BlightedItem blightedItem = BlightedItem.fromItemStack(rodStack);
+ if (blightedItem != null && blightedItem.getItemType() == requiredType) {
+ return rodStack;
+ }
}
+ return null;
+ }
- ItemStack offhandItem = player.getInventory().getItemInOffHand();
- if (isRodMaterial(offhandItem)) {
- return offhandItem.getEnchantmentLevel(Enchantment.LUCK_OF_THE_SEA);
- }
- return 0;
+ private int resolveVanillaLuckLevel(Player player) {
+ ItemStack rodStack = getHeldFishingRodStack(player);
+ return rodStack != null ? rodStack.getEnchantmentLevel(Enchantment.LUCK_OF_THE_SEA) : 0;
}
private boolean isRodMaterial(ItemStack itemStack) {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
index 7b1a8851..24a44d36 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
@@ -16,6 +16,7 @@
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.persistence.PersistentDataContainer;
@@ -33,17 +34,14 @@ public BlightedBlockListener() {
}
private String getBlockId(Block block) {
- if (block.hasMetadata("blighted_id")) {
- for (MetadataValue value : block.getMetadata("blighted_id")) {
- if (value.getOwningPlugin() == plugin) return value.asString();
- }
+ List metadata = block.getMetadata("blighted_id");
+ for (MetadataValue value : metadata) {
+ if (value.getOwningPlugin() == plugin) return value.asString();
}
- BlockState state = block.getState();
- if (state instanceof TileState tile) {
- PersistentDataContainer pdc = tile.getPersistentDataContainer();
- if (pdc.has(BLOCK_ID_KEY, PersistentDataType.STRING)) {
- String id = pdc.get(BLOCK_ID_KEY, PersistentDataType.STRING);
+ if (block.getState() instanceof TileState tile) {
+ String id = tile.getPersistentDataContainer().get(BLOCK_ID_KEY, PersistentDataType.STRING);
+ if (id != null) {
cacheMetadata(block, id);
return id;
}
@@ -62,9 +60,10 @@ public void onBlockPlace(BlockPlaceEvent event) {
ItemStack item = event.getItemInHand();
if (!item.hasItemMeta()) return;
- var meta = item.getItemMeta();
- String id = Objects.requireNonNull(meta).getPersistentDataContainer().get(BlightedItem.BLIGHTED_ID_KEY, PersistentDataType.STRING);
+ ItemMeta meta = item.getItemMeta();
+ if (meta == null) return;
+ String id = meta.getPersistentDataContainer().get(BlightedItem.BLIGHTED_ID_KEY, PersistentDataType.STRING);
if (id == null) return;
BlightedBlock customBlock = BlockRegistry.get(id);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/BlightedShapelessRecipe.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/BlightedShapelessRecipe.java
index f652121d..ef9535de 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/BlightedShapelessRecipe.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/BlightedShapelessRecipe.java
@@ -18,6 +18,7 @@ public final class BlightedShapelessRecipe extends BlightedRecipe {
private final List ingredientList = new ArrayList<>();
private final Map ingredientCountMap = new HashMap<>();
private final BlightedItem resultBlightedItem;
+ private final int resultAmount;
/**
* Ingredient acting as the attribute source.
@@ -26,7 +27,12 @@ public final class BlightedShapelessRecipe extends BlightedRecipe {
private CraftingObject attributeSourceIngredient = null;
public BlightedShapelessRecipe(BlightedItem resultBlightedItem) {
+ this(resultBlightedItem, 1);
+ }
+
+ public BlightedShapelessRecipe(BlightedItem resultBlightedItem, int resultAmount) {
this.resultBlightedItem = resultBlightedItem;
+ this.resultAmount = resultAmount;
}
@Override
@@ -36,7 +42,7 @@ public BlightedItem getResult() {
@Override
public int getAmount() {
- return 0;
+ return resultAmount;
}
/**
@@ -49,6 +55,7 @@ public int getAmount() {
@Override
public ItemStack assemble(List craftingGrid) {
ItemStack result = resultBlightedItem.toItemStack().clone();
+ result.setAmount(resultAmount);
if (attributeSourceIngredient != null) {
String targetId = attributeSourceIngredient.getId();
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java
index f9391616..4add925c 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapedRecipeBuilder.java
@@ -53,7 +53,11 @@ public static ShapedRecipeBuilder of(BlightedItem result, int amount) {
* @throws IllegalArgumentException if the item ID is not registered
*/
public static ShapedRecipeBuilder of(String resultId, int amount) {
- return new ShapedRecipeBuilder(ItemRegistry.get(resultId), amount);
+ BlightedItem result = ItemRegistry.get(resultId);
+ if (result == null) {
+ throw new IllegalArgumentException("Unknown recipe result item ID: '" + resultId + "'");
+ }
+ return new ShapedRecipeBuilder(result, amount);
}
/**
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
index b9601aa6..6040856f 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
@@ -19,25 +19,38 @@
public final class ShapelessRecipeBuilder {
private final BlightedItem result;
+ private final int amount;
private final List ingredients = new ArrayList<>();
private CraftingObject attributeSource = null;
- private ShapelessRecipeBuilder(BlightedItem result) {
+ private ShapelessRecipeBuilder(BlightedItem result, int amount) {
this.result = result;
+ this.amount = amount;
}
/**
- * Creates a builder for a shapeless recipe producing the specified item.
+ * Creates a builder for a shapeless recipe producing a single instance of the specified item.
*
* @param result the item produced by the recipe
* @return a new shapeless recipe builder
*/
public static ShapelessRecipeBuilder of(BlightedItem result) {
- return new ShapelessRecipeBuilder(result);
+ return of(result, 1);
}
/**
- * Creates a builder for a shapeless recipe producing the item registered
+ * Creates a builder for a shapeless recipe producing the specified item and amount.
+ *
+ * @param result the item produced by the recipe
+ * @param amount the amount produced by the recipe
+ * @return a new shapeless recipe builder
+ */
+ public static ShapelessRecipeBuilder of(BlightedItem result, int amount) {
+ return new ShapelessRecipeBuilder(result, amount);
+ }
+
+ /**
+ * Creates a builder for a shapeless recipe producing a single instance of the item registered
* under the specified ID.
*
* @param resultId the ID of the result item
@@ -45,7 +58,24 @@ public static ShapelessRecipeBuilder of(BlightedItem result) {
* @throws IllegalArgumentException if the item ID is not registered
*/
public static ShapelessRecipeBuilder of(String resultId) {
- return new ShapelessRecipeBuilder(ItemRegistry.get(resultId));
+ return of(resultId, 1);
+ }
+
+ /**
+ * Creates a builder for a shapeless recipe producing the item registered
+ * under the specified ID and amount.
+ *
+ * @param resultId the ID of the result item
+ * @param amount the amount produced by the recipe
+ * @return a new shapeless recipe builder
+ * @throws IllegalArgumentException if the item ID is not registered
+ */
+ public static ShapelessRecipeBuilder of(String resultId, int amount) {
+ BlightedItem result = ItemRegistry.get(resultId);
+ if (result == null) {
+ throw new IllegalArgumentException("Unknown recipe result item ID: '" + resultId + "'");
+ }
+ return new ShapelessRecipeBuilder(result, amount);
}
/**
@@ -186,7 +216,7 @@ public ShapelessRecipeBuilder addIngredient(
* @return the constructed shapeless recipe
*/
public BlightedShapelessRecipe build() {
- BlightedShapelessRecipe recipe = new BlightedShapelessRecipe(result);
+ BlightedShapelessRecipe recipe = new BlightedShapelessRecipe(result, amount);
for (CraftingObject ingredient : ingredients) {
recipe.addIngredient(ingredient);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/registry/RecipeRegistry.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/registry/RecipeRegistry.java
index 79486cb9..9cbae6ed 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/registry/RecipeRegistry.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/registry/RecipeRegistry.java
@@ -68,6 +68,16 @@ public static ShapedRecipeBuilder shapedRecipe(String resultId, int amount) {
return ShapedRecipeBuilder.of(resultId, amount);
}
+ /**
+ * Creates a builder for a shapeless custom recipe producing a single item.
+ *
+ * @param resultId the item ID of the recipe result
+ * @return a shapeless recipe builder
+ */
+ public static ShapelessRecipeBuilder shapelessRecipe(String resultId) {
+ return ShapelessRecipeBuilder.of(resultId, 1);
+ }
+
/**
* Creates a builder for a shapeless custom recipe.
*
@@ -76,7 +86,7 @@ public static ShapedRecipeBuilder shapedRecipe(String resultId, int amount) {
* @return a shapeless recipe builder
*/
public static ShapelessRecipeBuilder shapelessRecipe(String resultId, int amount) {
- return ShapelessRecipeBuilder.of(resultId);
+ return ShapelessRecipeBuilder.of(resultId, amount);
}
/**
From e36c6a0a28a1a887ff4bcb4b2121177a13d82a61 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:17:54 +0200
Subject: [PATCH 23/31] fix(menu): preserve empty slots in fillPattern and
update sign input NMS calls
- Fix Menu.fillPattern column calculation by preserving space character indices.
- Update SignInputMenu and SignInputListener for modern NMS sign packet structures.
- Streamline ItemRegistry lookups across BlightedSMP recipes.
---
.../java/fr/moussax/bedrock/ui/menu/Menu.java | 6 +-
.../bedrock/ui/sign/SignInputListener.java | 2 +-
.../bedrock/ui/sign/SignInputMenu.java | 3 +-
.../commands/impl/TestCommand.java | 22 +++-
.../blightedSMP/content/ContentRegistrar.java | 9 +-
.../content/items/BlightedItems.java | 8 +-
.../content/items/BlightedTools.java | 3 +-
.../blightedSMP/content/items/Bonemerang.java | 3 +-
.../content/items/GlimmeringEye.java | 4 +-
.../blightedSMP/content/items/Hyperion.java | 3 +-
.../content/items/KnightsSword.java | 3 +-
.../items/abilities/BonemerangAbility.java | 75 +++---------
.../items/abilities/KnightsSlamAbility.java | 24 ++--
.../items/abilities/VoidStepAbility.java | 31 ++---
.../items/abilities/WitherImpactAbility.java | 36 ++----
.../abilities/tools/AutosmeltAbility.java | 11 ++
.../items/abilities/tools/HammerAbility.java | 10 ++
.../items/abilities/tools/TimberAbility.java | 30 ++---
.../abilities/tools/VeinmineAbility.java | 11 ++
.../content/items/armors/FishingArmors.java | 110 +++++++++---------
.../content/items/blocks/BlightedForge.java | 2 +-
.../items/blocks/BlightedWorkbench.java | 2 +-
.../content/recipes/EndRecipes.java | 2 +-
.../content/recipes/EquipmentRecipes.java | 10 +-
.../content/recipes/FishingArmorsRecipes.java | 33 ++++--
.../content/recipes/ForgeRecipes.java | 4 +-
.../content/recipes/MaterialRecipes.java | 12 +-
.../recipes/NetherMaterialRecipes.java | 2 +-
.../content/rituals/AncientRituals.java | 2 +-
.../content/utils/ai/EndermanAI.java | 4 +-
.../engine/entities/BlightedEntity.java | 20 ++--
31 files changed, 237 insertions(+), 260 deletions(-)
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/ui/menu/Menu.java b/bedrock/src/main/java/fr/moussax/bedrock/ui/menu/Menu.java
index 917341ad..2765c7a7 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/ui/menu/Menu.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/ui/menu/Menu.java
@@ -649,9 +649,9 @@ public void fillBorder(@NonNull MenuElementPreset preset) {
*/
public void fillPattern(String[] pattern, char symbol, @NonNull ItemStack item) {
for (int row = 0; row < pattern.length && row < size / 9; row++) {
- String replaced = pattern[row].replace(" ", "");
- for (int column = 0; column < replaced.length() && column < 9; column++) {
- if (replaced.charAt(column) == symbol) {
+ String rowString = pattern[row];
+ for (int column = 0; column < rowString.length() && column < 9; column++) {
+ if (rowString.charAt(column) == symbol) {
setItem(getSlot(row, column), item);
}
}
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputListener.java b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputListener.java
index 10cbcf6c..33b7aca8 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputListener.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputListener.java
@@ -58,7 +58,7 @@ public void inject(Player player) {
public void channelRead(ChannelHandlerContext context, Object packet) throws Exception {
if (packet instanceof ServerboundSignUpdatePacket signPacket) {
if (SignInputManager.hasActiveSession(player.getUniqueId())) {
- SignInputManager.handleSignUpdate(player, signPacket.getLines());
+ SignInputManager.handleSignUpdate(player, signPacket.lines().toArray(String[]::new));
return;
}
}
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java
index f516c7de..4c1b53a0 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java
@@ -3,6 +3,7 @@
import fr.moussax.bedrock.scheduling.PluginContext;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket;
+import net.minecraft.world.level.block.entity.SignTextSlot;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -63,7 +64,7 @@ public void open(@NonNull Player player) {
if (!player.isOnline()) {
return;
}
- nmsPlayer.connection.send(new ClientboundOpenSignEditorPacket(blockPosition, frontSide));
+ nmsPlayer.connection.send(new ClientboundOpenSignEditorPacket(blockPosition, frontSide ? SignTextSlot.FRONT : SignTextSlot.BACK));
SignInputManager.register(player.getUniqueId(), this, blockPosition);
}, 2L);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/commands/impl/TestCommand.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/commands/impl/TestCommand.java
index a4fa96f8..8bf4b8c3 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/commands/impl/TestCommand.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/commands/impl/TestCommand.java
@@ -1,16 +1,32 @@
package fr.moussax.blightedSMP.commands.impl;
+import fr.moussax.bedrock.utils.ItemBuilder;
import fr.moussax.blightedSMP.commands.AdminCommand;
-import fr.moussax.bedrock.ui.toast.AdvancementToast;
import org.bukkit.Material;
import org.bukkit.command.Command;
+import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
public final class TestCommand extends AdminCommand {
@Override
protected boolean executeAdmin(Player player, Command command, String label, String[] args) {
- AdvancementToast.task(player, "Command looped 50x for 2 ticks", Material.REPEATING_COMMAND_BLOCK);
- AdvancementToast.challenge(player, "Call the Corrupted Champion", Material.SCULK_SHRIEKER);
+
+ ItemStack item = new ItemBuilder(Material.COPPER_HELMET)
+ .setDisplayName("§fAngler Helmet")
+ .addEnchantment(Enchantment.UNBREAKING, 5)
+ .addItemFlag(ItemFlag.HIDE_ATTRIBUTES)
+ .addLore("",
+ " §8A simple garb from a simple ",
+ " §8craft. Though beneath the",
+ " §8surface, nothing is ever",
+ " §8quite so simple.",
+ "", "§f§lCOMMON"
+ )
+ .toItemStack();
+
+ player.getInventory().addItem(item);
return true;
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/ContentRegistrar.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/ContentRegistrar.java
index 30706c9c..c7edd195 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/ContentRegistrar.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/ContentRegistrar.java
@@ -21,11 +21,7 @@
import fr.moussax.blightedSMP.content.items.materials.EndMaterials;
import fr.moussax.blightedSMP.content.items.materials.FishingMaterials;
import fr.moussax.blightedSMP.content.items.materials.NetherMaterials;
-import fr.moussax.blightedSMP.content.recipes.EndRecipes;
-import fr.moussax.blightedSMP.content.recipes.EquipmentRecipes;
-import fr.moussax.blightedSMP.content.recipes.ForgeRecipes;
-import fr.moussax.blightedSMP.content.recipes.MaterialRecipes;
-import fr.moussax.blightedSMP.content.recipes.NetherMaterialRecipes;
+import fr.moussax.blightedSMP.content.recipes.*;
import fr.moussax.blightedSMP.content.rituals.AncientRituals;
import fr.moussax.blightedSMP.engine.entities.BlightedEntity;
import fr.moussax.blightedSMP.engine.entities.rituals.AncientRitual;
@@ -75,7 +71,8 @@ private ContentRegistrar() {
new MaterialRecipes(),
new NetherMaterialRecipes(),
new EndRecipes(),
- new EquipmentRecipes()
+ new EquipmentRecipes(),
+ new FishingArmorsRecipes()
);
public static final List>> FORGE_MODULES = List.of(
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedItems.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedItems.java
index f2fedf20..e3a3df46 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedItems.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedItems.java
@@ -3,7 +3,6 @@
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import java.util.function.Consumer;
import fr.moussax.blightedSMP.engine.items.rules.ItemRule;
@@ -82,7 +81,7 @@ public void register(Consumer registry) {
"§5 abomination§7. Within its core lie §dGems ",
"§7 sealed and waiting for a daring",
"§7 hand to claim them.",
- "§8 Gems: §d1✵",
+ "§8 Ges: §d1✵",
"",
"§d Right click to consume!",
"",
@@ -92,10 +91,7 @@ public void register(Consumer registry) {
blightedGemstone.preventEquipping();
blightedGemstone.unstackable();
blightedGemstone.addRule(ItemRule.PREVENT_PLACEMENT);
- blightedGemstone.addAbility(
- Ability.rightClick("Consume Gems", new GemsItem.BlightedGemstoneAbility()),
- false
- );
+ blightedGemstone.addAbility(new GemsItem.BlightedGemstoneAbility(), false);
registry.accept(blightedBanner);
registry.accept(blightedCodex);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedTools.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedTools.java
index b86c384d..79914bcc 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedTools.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/BlightedTools.java
@@ -4,7 +4,6 @@
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import fr.moussax.blightedSMP.registry.RegistryModule;
import org.bukkit.Material;
@@ -35,7 +34,7 @@ public void register(Consumer registry) {
BlightedItem demoPickaxe = new BlightedItem("DEMO_PICKAXE", ItemType.PICKAXE, ItemRarity.SPECIAL, Material.DIAMOND_PICKAXE);
demoPickaxe.setDisplayName("Demo Pickaxe");
- demoPickaxe.addAbility(Ability.passive("Veinmine", new VeinmineAbility()));
+ demoPickaxe.addAbility(new VeinmineAbility());
demoPickaxe.addLore("§8Demonstration tool");
registry.accept(demoPickaxe);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Bonemerang.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Bonemerang.java
index db7e8182..d6e9ace1 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Bonemerang.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Bonemerang.java
@@ -4,7 +4,6 @@
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import fr.moussax.blightedSMP.registry.RegistryModule;
import java.util.function.Consumer;
import org.bukkit.Material;
@@ -24,7 +23,7 @@ public void register(Consumer registry) {
"",
ItemRarity.EPIC.getName() + " BOW"
);
- bonemerang.addAbility(Ability.rightClick("Swing", new BonemerangAbility()), false);
+ bonemerang.addAbility(new BonemerangAbility(), false);
bonemerang.addEnchantmentGlint();
bonemerang.unstackable();
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/GlimmeringEye.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/GlimmeringEye.java
index 4f0be145..e5c772ee 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/GlimmeringEye.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/GlimmeringEye.java
@@ -4,7 +4,6 @@
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import fr.moussax.blightedSMP.registry.RegistryModule;
import java.util.function.Consumer;
import fr.moussax.blightedSMP.engine.items.rules.ItemRule;
@@ -17,9 +16,8 @@ public void register(Consumer registry) {
BlightedItem glimmeringEye = new BlightedItem("GLIMMERING_EYE", ItemType.UNCATEGORIZED, ItemRarity.RARE, Material.ENDER_EYE);
glimmeringEye.setDisplayName("Glimmering Eye");
- Ability voidStep = Ability.rightClick("Voidstep", new VoidStepAbility());
glimmeringEye.addEnchantmentGlint();
- glimmeringEye.addAbility(voidStep);
+ glimmeringEye.addAbility(new VoidStepAbility());
glimmeringEye.addLore("", ItemRarity.RARE.getName());
glimmeringEye.addRule(ItemRule.PREVENT_PROJECTILE_LAUNCH);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Hyperion.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Hyperion.java
index c56c0fb9..d1393924 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Hyperion.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/Hyperion.java
@@ -4,7 +4,6 @@
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import fr.moussax.blightedSMP.registry.RegistryModule;
import java.util.function.Consumer;
import org.bukkit.Material;
@@ -28,7 +27,7 @@ public void register(Consumer registry) {
);
hyperion.setUnbreakable(true);
hyperion.addItemFlag(ItemFlag.HIDE_UNBREAKABLE);
- hyperion.addAbility(Ability.rightClick("Wither Impact", new WitherImpactAbility()), false);
+ hyperion.addAbility(new WitherImpactAbility(), false);
registry.accept(hyperion);
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/KnightsSword.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/KnightsSword.java
index 032423f1..03fe7fc9 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/KnightsSword.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/KnightsSword.java
@@ -4,7 +4,6 @@
import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
-import fr.moussax.blightedSMP.engine.items.abilities.Ability;
import fr.moussax.blightedSMP.registry.RegistryModule;
import java.util.function.Consumer;
import org.bukkit.Material;
@@ -29,7 +28,7 @@ public void register(Consumer registry) {
ItemRarity.LEGENDARY.getName() + " LONGSWORD"
);
- knightSword.addAbility(Ability.rightClick("Knight's Slam", new KnightsSlamAbility()), false);
+ knightSword.addAbility(new KnightsSlamAbility(), false);
knightSword.addAttributeModifier(Attribute.ATTACK_DAMAGE, 10, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.MAINHAND);
knightSword.addAttributeModifier(Attribute.ATTACK_SPEED, 1.2, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.MAINHAND);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java
index 9014f5b7..cc13bfb9 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java
@@ -2,9 +2,8 @@
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
-import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import org.bukkit.Material;
-import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.ArmorStand;
@@ -13,20 +12,15 @@
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
-import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
public class BonemerangAbility implements AbilityManager {
- private static final NamespacedKey UUID_KEY = new NamespacedKey(BlightedSMP.getInstance(), "bonemerang_uuid");
- private static final Map> cooldowns = new ConcurrentHashMap<>();
-
private static final int OUTBOUND_TICKS = 13;
private static final int RETURN_TICKS = 13;
private static final double PROJECTILE_SPEED = 1.16;
@@ -35,6 +29,16 @@ public class BonemerangAbility implements AbilityManager {
private static final double SPAWN_HEIGHT_OFFSET = 1.1;
private static final double ROTATION_SPEED = 35.0;
+ @Override
+ public String getName() {
+ return "Swing";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.RIGHT_CLICK;
+ }
+
@Override
public boolean triggerAbility(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) {
@@ -48,14 +52,6 @@ public boolean triggerAbility(PlayerInteractEvent event) {
return false;
}
- String itemUuid = getOrAssignItemUuid(hand);
-
- if (isItemOnCooldown(player, itemUuid)) {
- return false;
- }
-
- setItemCooldown(player, itemUuid, getCooldownSeconds());
-
ItemStack thrownCopy = hand.clone();
reduceStackInHand(player, hand);
setThrownVisualInHand(player, thrownCopy);
@@ -66,50 +62,7 @@ public boolean triggerAbility(PlayerInteractEvent event) {
@Override
public int getCooldownSeconds() {
- return 0;
- }
-
- @Override
- public int getManaCost() {
- return 0;
- }
-
- @Override
- public boolean canTrigger(BlightedPlayer player) {
- return true;
- }
-
- @Override
- public void start(BlightedPlayer player) {
- }
-
- @Override
- public void stop(BlightedPlayer player) {
- }
-
- private boolean isItemOnCooldown(Player player, String uuid) {
- Map playerCooldowns = cooldowns.computeIfAbsent(player.getUniqueId(), k -> new ConcurrentHashMap<>());
- long currentTime = System.currentTimeMillis();
- return playerCooldowns.getOrDefault(uuid, 0L) > currentTime;
- }
-
- private void setItemCooldown(Player player, String uuid, int seconds) {
- cooldowns.computeIfAbsent(player.getUniqueId(), k -> new ConcurrentHashMap<>())
- .put(uuid, System.currentTimeMillis() + (seconds * 1000L));
- }
-
- private String getOrAssignItemUuid(ItemStack item) {
- var meta = item.getItemMeta();
- if (meta == null) {
- return "LEGACY";
- }
-
- var container = meta.getPersistentDataContainer();
- if (!container.has(UUID_KEY, PersistentDataType.STRING)) {
- container.set(UUID_KEY, PersistentDataType.STRING, UUID.randomUUID().toString());
- item.setItemMeta(meta);
- }
- return container.get(UUID_KEY, PersistentDataType.STRING);
+ return 2;
}
private void reduceStackInHand(Player player, ItemStack hand) {
@@ -248,7 +201,7 @@ private void returnItem(Player player, String expectedName, ItemStack original)
}
}
- private boolean replaceNuggetWithOriginal(org.bukkit.inventory.Inventory inventory, ItemStack original) {
+ private boolean replaceNuggetWithOriginal(Inventory inventory, ItemStack original) {
for (int i = 0; i < inventory.getSize(); i++) {
ItemStack slot = inventory.getItem(i);
if (isSameCustomNugget(slot, original)) {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java
index 62eb5f79..db71731c 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java
@@ -2,6 +2,7 @@
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -20,32 +21,29 @@
public class KnightsSlamAbility implements AbilityManager {
@Override
- public boolean triggerAbility(PlayerInteractEvent event) {
- new KnightSword(event.getPlayer().getTargetBlock(null, 6).getLocation(), BlightedPlayer.getBlightedPlayer(event.getPlayer()));
- return true;
- }
-
- @Override
- public int getCooldownSeconds() {
- return 30;
+ public String getName() {
+ return "Knight's Slam";
}
@Override
- public int getManaCost() {
- return 20;
+ public AbilityType getType() {
+ return AbilityType.RIGHT_CLICK;
}
@Override
- public boolean canTrigger(BlightedPlayer player) {
+ public boolean triggerAbility(PlayerInteractEvent event) {
+ new KnightSword(event.getPlayer().getTargetBlock(null, 6).getLocation(), BlightedPlayer.get(event.getPlayer()));
return true;
}
@Override
- public void start(BlightedPlayer player) {
+ public int getCooldownSeconds() {
+ return 30;
}
@Override
- public void stop(BlightedPlayer player) {
+ public int getManaCost() {
+ return 20;
}
private static class KnightSword extends BukkitRunnable {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/VoidStepAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/VoidStepAbility.java
index bb66389f..b3ce634b 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/VoidStepAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/VoidStepAbility.java
@@ -1,6 +1,7 @@
package fr.moussax.blightedSMP.content.items.abilities;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import fr.moussax.bedrock.text.Messenger;
import org.bukkit.*;
@@ -14,6 +15,16 @@
public class VoidStepAbility implements AbilityManager {
private static final int MAX_DISTANCE = 40;
+ @Override
+ public String getName() {
+ return "Voidstep";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.RIGHT_CLICK;
+ }
+
@Override
public String[] getDescription() {
return new String[]{
@@ -25,7 +36,7 @@ public String[] getDescription() {
@Override
public boolean triggerAbility(PlayerInteractEvent event) {
- BlightedPlayer blightedPlayer = BlightedPlayer.getBlightedPlayer(event.getPlayer());
+ BlightedPlayer blightedPlayer = BlightedPlayer.get(event.getPlayer());
Location targetLocation = getTargetedEyeLocation(blightedPlayer);
if (targetLocation == null) {
@@ -54,29 +65,11 @@ public boolean triggerAbility(PlayerInteractEvent event) {
return true;
}
- @Override
- public int getCooldownSeconds() {
- return 0;
- }
-
@Override
public int getManaCost() {
return 5;
}
- @Override
- public boolean canTrigger(BlightedPlayer player) {
- return true;
- }
-
- @Override
- public void start(BlightedPlayer player) {
- }
-
- @Override
- public void stop(BlightedPlayer player) {
- }
-
private Location getTargetedEyeLocation(BlightedPlayer blightedPlayer) {
var player = blightedPlayer.getPlayer();
var eyeLocation = player.getEyeLocation();
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java
index f2f4438f..e27c8877 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java
@@ -2,6 +2,7 @@
import fr.moussax.blightedSMP.BlightedSMP;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.items.registry.ItemRegistry;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import fr.moussax.bedrock.text.Formatter;
@@ -35,6 +36,16 @@ public class WitherImpactAbility implements AbilityManager,
private final double DAMAGE_RANGE = 5.0;
private final long HEALING_COOLDOWN = 5000L;
+ @Override
+ public String getName() {
+ return "Wither Impact";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.RIGHT_CLICK;
+ }
+
@Override
public boolean triggerAbility(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) {
@@ -56,31 +67,8 @@ public boolean triggerAbility(PlayerInteractEvent event) {
return true;
}
- @Override
- public int getCooldownSeconds() {
- return 0;
- }
-
- @Override
- public int getManaCost() {
- return 0;
- }
-
- @Override
- public boolean canTrigger(BlightedPlayer player) {
- return true;
- }
-
- @Override
- public void start(BlightedPlayer player) {
- }
-
- @Override
- public void stop(BlightedPlayer player) {
- }
-
private boolean isHoldingHyperion(Player player) {
- return player.getInventory().getItemInMainHand().equals(ItemRegistry.getItem("HYPERION").toItemStack());
+ return player.getInventory().getItemInMainHand().equals(ItemRegistry.get("HYPERION").toItemStack());
}
private void teleport(Player player) {
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/AutosmeltAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/AutosmeltAbility.java
index e8f3ff2e..3d76d0ea 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/AutosmeltAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/AutosmeltAbility.java
@@ -1,6 +1,7 @@
package fr.moussax.blightedSMP.content.items.abilities.tools;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import org.bukkit.Material;
import org.bukkit.event.block.BlockDropItemEvent;
@@ -10,6 +11,16 @@
public class AutosmeltAbility implements AbilityManager {
+ @Override
+ public String getName() {
+ return "Autosmelt";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.PASSIVE;
+ }
+
private static final Map SMELTABLE = Map.ofEntries(
Map.entry(Material.COBBLESTONE, Material.STONE),
Map.entry(Material.STONE, Material.SMOOTH_STONE),
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/HammerAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/HammerAbility.java
index 3a04c932..1de03ef5 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/HammerAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/HammerAbility.java
@@ -1,10 +1,20 @@
package fr.moussax.blightedSMP.content.items.abilities.tools;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import org.bukkit.event.block.BlockBreakEvent;
public class HammerAbility implements AbilityManager {
+ @Override
+ public String getName() {
+ return "Hammer";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.PASSIVE;
+ }
@Override
public boolean triggerAbility(BlockBreakEvent event) {
return false;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/TimberAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/TimberAbility.java
index 73ea02f5..5e24f8ff 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/TimberAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/TimberAbility.java
@@ -1,6 +1,7 @@
package fr.moussax.blightedSMP.content.items.abilities.tools;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -10,6 +11,16 @@
public class TimberAbility implements AbilityManager {
+ @Override
+ public String getName() {
+ return "Timber";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.PASSIVE;
+ }
+
private static final int MAX_LOGS = 32;
private static final Set LOGS = Set.of(
Material.OAK_LOG, Material.OAK_WOOD,
@@ -99,23 +110,4 @@ public int getCooldownSeconds() {
return 2;
}
- @Override
- public int getManaCost() {
- return 0;
- }
-
- @Override
- public boolean canTrigger(BlightedPlayer player) {
- return true;
- }
-
- @Override
- public void start(BlightedPlayer player) {
-
- }
-
- @Override
- public void stop(BlightedPlayer player) {
-
- }
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/VeinmineAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/VeinmineAbility.java
index 41daebd9..971b21d7 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/VeinmineAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/tools/VeinmineAbility.java
@@ -1,6 +1,7 @@
package fr.moussax.blightedSMP.content.items.abilities.tools;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
+import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -10,6 +11,16 @@
public class VeinmineAbility implements AbilityManager {
+ @Override
+ public String getName() {
+ return "Veinmine";
+ }
+
+ @Override
+ public AbilityType getType() {
+ return AbilityType.PASSIVE;
+ }
+
private static final int MAX_BLOCK = 64;
private static final Set VEIN_BLOCKS = Set.of(
Material.COAL_ORE,
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/armors/FishingArmors.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/armors/FishingArmors.java
index a5fe3c38..ad53b54b 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/armors/FishingArmors.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/armors/FishingArmors.java
@@ -6,9 +6,8 @@
import fr.moussax.blightedSMP.engine.items.ItemRarity;
import fr.moussax.blightedSMP.engine.items.ItemType;
import fr.moussax.blightedSMP.engine.items.abilities.FullSetBonus;
-import fr.moussax.blightedSMP.registry.RegistryModule;
-import java.util.function.Consumer;
import fr.moussax.blightedSMP.engine.items.rules.ItemRule;
+import fr.moussax.blightedSMP.registry.RegistryModule;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
@@ -18,12 +17,65 @@
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
+import java.util.function.Consumer;
+
public final class FishingArmors implements RegistryModule> {
@SuppressWarnings("UnstableApiUsage")
@Override
public void register(Consumer registry) {
+ String[] anglerArmorLore = new String[]{
+ "",
+ " §8A simple garb from a simple ",
+ " §8craft. Though beneath the",
+ " §8surface, nothing is ever",
+ " §8quite so simple.", "",
+ ItemRarity.COMMON.getName()
+ };
+
+ BlightedItem anglerHelmet = new BlightedItem("ANGLER_HELMET", ItemType.HELMET, ItemRarity.COMMON, Material.COPPER_HELMET);
+ anglerHelmet.setDisplayName("Angler Helmet");
+ anglerHelmet.addAttributeModifier(Attribute.ARMOR, 2.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.HEAD);
+ anglerHelmet.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.HEAD);
+ anglerHelmet.addItemFlag(ItemFlag.HIDE_ATTRIBUTES);
+ anglerHelmet.addLore(anglerArmorLore);
+ anglerHelmet.setMaxDurability(121);
+
+ BlightedItem anglerChestplate = new BlightedItem("ANGLER_CHESTPLATE", ItemType.CHESTPLATE, ItemRarity.COMMON, Material.LEATHER_CHESTPLATE);
+ anglerChestplate.setDisplayName("Angler Chestplate");
+ anglerChestplate.addAttributeModifier(Attribute.ARMOR, 4.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.CHEST);
+ anglerChestplate.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.CHEST);
+ anglerChestplate.addItemFlag(ItemFlag.HIDE_DYE, ItemFlag.HIDE_ATTRIBUTES);
+ anglerChestplate.addLore(anglerArmorLore);
+ anglerChestplate.setLeatherColor("#2B457A");
+ anglerChestplate.setMaxDurability(176);
+
+ BlightedItem anglerLeggings = new BlightedItem("ANGLER_LEGGINGS", ItemType.LEGGINGS, ItemRarity.COMMON, Material.LEATHER_LEGGINGS);
+ anglerLeggings.setDisplayName("Angler Leggings");
+ anglerLeggings.addAttributeModifier(Attribute.ARMOR, 3.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.LEGS);
+ anglerLeggings.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.LEGS);
+ anglerLeggings.addItemFlag(ItemFlag.HIDE_DYE, ItemFlag.HIDE_ATTRIBUTES);
+ anglerLeggings.addLore(anglerArmorLore);
+ anglerLeggings.setLeatherColor("#2B457A");
+ anglerLeggings.setMaxDurability(165);
+
+ BlightedItem anglerBoots = new BlightedItem("ANGLER_BOOTS", ItemType.BOOTS, ItemRarity.COMMON, Material.LEATHER_BOOTS);
+ anglerBoots.setDisplayName("Angler Boots");
+ anglerBoots.addAttributeModifier(Attribute.ARMOR, 1.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.FEET);
+ anglerBoots.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.FEET);
+ anglerBoots.addItemFlag(ItemFlag.HIDE_DYE, ItemFlag.HIDE_ATTRIBUTES);
+ anglerBoots.addLore(anglerArmorLore);
+ anglerBoots.setLeatherColor("#2B457A");
+
+ registry.accept(anglerHelmet);
+ registry.accept(anglerChestplate);
+ registry.accept(anglerLeggings);
+ registry.accept(anglerBoots);
+
+
+
+
FullSetBonus emberWeaveSetBonus = new EmberWeaveSetBonus();
BlightedItem emberWeaveHelmet = new BlightedItem("EMBERWEAVE_HELMET", ItemType.HELMET, ItemRarity.RARE, Material.PLAYER_HEAD);
@@ -118,56 +170,6 @@ public void register(Consumer registry) {
ashfangBoots.setFullSetBonus(magmaWeaveSetBonus);
ashfangBoots.addLore("", ItemRarity.EPIC.getName() + " BOOTS");
- String[] anglerLore = new String[]{
- "",
- " §7Worn by those who cast lines",
- " §7into the §9Deep Seas§7. A relic of",
- " §7forgotten tradition, guiding",
- " §7the path toward mastery."
- };
-
- BlightedItem anglerHelmet = new BlightedItem("ANGLER_HELMET", ItemType.HELMET, ItemRarity.UNCOMMON, Material.COPPER_HELMET);
- anglerHelmet.setDisplayName("Angler Helmet");
- anglerHelmet.addLore(anglerLore);
- anglerHelmet.addAttributeModifier(Attribute.ARMOR, 2.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.HEAD);
- anglerHelmet.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.HEAD);
- anglerHelmet.addAttributeModifier(Attribute.LUCK, 0.25, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.HEAD);
- anglerHelmet.setMaxDurability(121);
- anglerHelmet.addLore("", ItemRarity.UNCOMMON.getName() + " HELMET");
-
- BlightedItem anglerChestplate = new BlightedItem("ANGLER_CHESTPLATE", ItemType.CHESTPLATE, ItemRarity.UNCOMMON, Material.LEATHER_CHESTPLATE);
- anglerChestplate.setDisplayName("Angler Chestplate");
- anglerChestplate.addLore(anglerLore);
- anglerChestplate.addAttributeModifier(Attribute.ARMOR, 4.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.CHEST);
- anglerChestplate.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.CHEST);
- anglerChestplate.addAttributeModifier(Attribute.LUCK, 0.25, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.CHEST);
- anglerChestplate.addItemFlag(ItemFlag.HIDE_DYE);
- anglerChestplate.setLeatherColor("#4B6D9E");
- anglerChestplate.setMaxDurability(176);
- anglerChestplate.addLore("", ItemRarity.UNCOMMON.getName() + " CHESTPLATE");
-
- BlightedItem anglerLeggings = new BlightedItem("ANGLER_LEGGINGS", ItemType.LEGGINGS, ItemRarity.UNCOMMON, Material.LEATHER_LEGGINGS);
- anglerLeggings.setDisplayName("Angler Leggings");
- anglerLeggings.addLore(anglerLore);
- anglerLeggings.addAttributeModifier(Attribute.ARMOR, 3.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.LEGS);
- anglerLeggings.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.LEGS);
- anglerLeggings.addAttributeModifier(Attribute.LUCK, 0.25, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.LEGS);
- anglerLeggings.addItemFlag(ItemFlag.HIDE_DYE);
- anglerLeggings.setLeatherColor("#4B6D9E");
- anglerLeggings.setMaxDurability(165);
- anglerLeggings.addLore("", ItemRarity.UNCOMMON.getName() + " LEGGINGS");
-
- BlightedItem anglerBoots = new BlightedItem("ANGLER_BOOTS", ItemType.BOOTS, ItemRarity.UNCOMMON, Material.LEATHER_BOOTS);
- anglerBoots.setDisplayName("Angler Boots");
- anglerBoots.addLore(anglerLore);
- anglerBoots.addAttributeModifier(Attribute.ARMOR, 1.0, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.FEET);
- anglerBoots.addAttributeModifier(Attribute.OXYGEN_BONUS, 0.5, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.FEET);
- anglerBoots.addAttributeModifier(Attribute.LUCK, 0.25, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlotGroup.FEET);
- anglerBoots.addItemFlag(ItemFlag.HIDE_DYE);
- anglerBoots.setLeatherColor("#4B6D9E");
- anglerBoots.setMaxDurability(143);
- anglerBoots.addLore("", ItemRarity.UNCOMMON.getName() + " BOOTS");
-
registry.accept(emberWeaveHelmet);
registry.accept(emberWeaveChestplate);
registry.accept(emberWeaveLeggins);
@@ -176,9 +178,5 @@ public void register(Consumer registry) {
registry.accept(ashfangChestplate);
registry.accept(ashfangLeggins);
registry.accept(ashfangBoots);
- registry.accept(anglerHelmet);
- registry.accept(anglerChestplate);
- registry.accept(anglerLeggings);
- registry.accept(anglerBoots);
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedForge.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedForge.java
index 8c638006..97db4072 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedForge.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedForge.java
@@ -12,7 +12,7 @@ public class BlightedForge extends BlightedBlock {
public static BlightedForge instance;
public BlightedForge() {
- super(Material.BLAST_FURNACE, ItemRegistry.getItem("BLIGHTED_FORGE"));
+ super(Material.BLAST_FURNACE, ItemRegistry.get("BLIGHTED_FORGE"));
}
@Override
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedWorkbench.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedWorkbench.java
index c3ed4d15..9c6f2389 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedWorkbench.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/blocks/BlightedWorkbench.java
@@ -14,7 +14,7 @@
public class BlightedWorkbench extends BlightedBlock {
public BlightedWorkbench() {
- super(Material.ENCHANTING_TABLE, ItemRegistry.getItem("BLIGHTED_WORKBENCH"));
+ super(Material.ENCHANTING_TABLE, ItemRegistry.get("BLIGHTED_WORKBENCH"));
}
@Override
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EndRecipes.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EndRecipes.java
index 6c0cdf95..c95da515 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EndRecipes.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EndRecipes.java
@@ -30,7 +30,7 @@ public void register(Consumer registry) {
BlightedRecipe glimmeringEyeRecipe = shapedRecipe("GLIMMERING_EYE", 1)
.shape(" i ", "iji", " i ")
- .bind('i', ItemRegistry.getItem("ENCHANTED_ENDER_PEARL"), 1)
+ .bind('i', ItemRegistry.get("ENCHANTED_ENDER_PEARL"), 1)
.bind('j', Material.OPEN_EYEBLOSSOM, 1)
.build();
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EquipmentRecipes.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EquipmentRecipes.java
index 0ca20c90..74772219 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EquipmentRecipes.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/EquipmentRecipes.java
@@ -12,11 +12,11 @@ public final class EquipmentRecipes implements RegistryModule registry) {
BlightedRecipe rocketBoots = shapedRecipe("ROCKET_BOOTS", 1)
.shape("aba", "cdc", "e e")
- .bind('a', Material.PHANTOM_MEMBRANE, 1)
- .bind('b', Material.WIND_CHARGE, 1)
- .bind('c', Material.SLIME_BLOCK, 1)
- .bind('d', Material.COPPER_BOOTS, 1)
- .bind('e', Material.RABBIT_FOOT, 1)
+ .bind('a', Material.PHANTOM_MEMBRANE)
+ .bind('b', Material.WIND_CHARGE)
+ .bind('c', Material.SLIME_BLOCK)
+ .bind('d', Material.COPPER_BOOTS)
+ .bind('e', Material.RABBIT_FOOT)
.attributeSource(4)
.build();
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/FishingArmorsRecipes.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/FishingArmorsRecipes.java
index 885eaaff..dccdbf61 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/FishingArmorsRecipes.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/FishingArmorsRecipes.java
@@ -2,21 +2,40 @@
import fr.moussax.blightedSMP.engine.items.recipes.crafting.BlightedRecipe;
import fr.moussax.blightedSMP.registry.RegistryModule;
+import org.bukkit.Material;
import java.util.function.Consumer;
import static fr.moussax.blightedSMP.engine.items.recipes.crafting.registry.RecipeRegistry.shapedRecipe;
-public class AnglerArmorRecipe implements RegistryModule> {
+public final class FishingArmorsRecipes implements RegistryModule> {
@Override
public void register(Consumer registry) {
- BlightedRecipe anglerHelmet = shapedRecipe("ANGLER_HELMET")
-
-
-
-
-
+ BlightedRecipe anglerHelmetRecipe = shapedRecipe("ANGLER_HELMET", 1)
+ .shape("aaa", "a a", " ")
+ .bind('a', Material.COD, 2)
+ .build();
+
+ BlightedRecipe anglerChestplateRecipe = shapedRecipe("ANGLER_CHESTPLATE", 1)
+ .shape("a a", "aaa", "aaa")
+ .bind('a', Material.COD, 2)
+ .build();
+
+ BlightedRecipe anglerLeggingsRecipe = shapedRecipe("ANGLER_LEGGINGS", 1)
+ .shape("aaa", "a a", "a a")
+ .bind('a', Material.COD, 2)
+ .build();
+
+ BlightedRecipe anglerBootsRecipe = shapedRecipe("ANGLER_BOOTS", 1)
+ .shape(" ", "a a", "a a")
+ .bind('a', Material.COD, 2)
+ .build();
+
+ registry.accept(anglerHelmetRecipe);
+ registry.accept(anglerChestplateRecipe);
+ registry.accept(anglerLeggingsRecipe);
+ registry.accept(anglerBootsRecipe);
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/ForgeRecipes.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/ForgeRecipes.java
index ea2ca747..5e99998a 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/ForgeRecipes.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/ForgeRecipes.java
@@ -13,8 +13,8 @@ public void register(Consumer registry) {
var plasmaBucket = ForgeRecipe.Builder.of("PLASMA_BUCKET", 1)
.fuelCost(10000)
.ingredients(
- new CraftingObject(ItemRegistry.getItem("MAGMA_BUCKET"), 1),
- new CraftingObject(ItemRegistry.getItem("MAGMA_BUCKET"), 1),
+ new CraftingObject(ItemRegistry.get("MAGMA_BUCKET"), 1),
+ new CraftingObject(ItemRegistry.get("MAGMA_BUCKET"), 1),
new CraftingObject(Material.NETHER_STAR, 1)
)
.build();
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/MaterialRecipes.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/MaterialRecipes.java
index 2434bfd9..255ccf5d 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/MaterialRecipes.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/MaterialRecipes.java
@@ -30,7 +30,7 @@ public void register(Consumer registry) {
BlightedRecipe enchantedIronBlockRecipe = shapedRecipe("ENCHANTED_IRON_BLOCK", 1)
.shape(" e ", "eee", " e ")
- .bind('e', ItemRegistry.getItem("ENCHANTED_IRON_INGOT"), 8)
+ .bind('e', ItemRegistry.get("ENCHANTED_IRON_INGOT"), 8)
.build();
BlightedRecipe enchantedGoldIngotRecipe = shapedRecipe("ENCHANTED_GOLD_INGOT", 1)
@@ -142,7 +142,7 @@ public void register(Consumer registry) {
var enchantedLavaBucketRecipe = shapedRecipe("ENCHANTED_LAVA_BUCKET", 1)
.shape("aaa", "bcb", " b ")
- .bind('a', ItemRegistry.getItem("ENCHANTED_COAL"), 1)
+ .bind('a', ItemRegistry.get("ENCHANTED_COAL"), 1)
.bind('b', Material.IRON_INGOT, 10)
.bind('c', Material.LAVA_BUCKET, 1)
.build();
@@ -150,8 +150,8 @@ public void register(Consumer registry) {
var magmaBucketRecipe = shapedRecipe("MAGMA_BUCKET", 1)
.shape("aaa", "bcb", " b ")
.bind('a', Material.MAGMA_BLOCK, 64)
- .bind('b', ItemRegistry.getItem("ENCHANTED_IRON_INGOT"), 4)
- .bind('c', ItemRegistry.getItem("ENCHANTED_LAVA_BUCKET"), 1)
+ .bind('b', ItemRegistry.get("ENCHANTED_IRON_INGOT"), 4)
+ .bind('c', ItemRegistry.get("ENCHANTED_LAVA_BUCKET"), 1)
.build();
var blightedCraftingTable = shapedRecipe("BLIGHTED_WORKBENCH", 1)
@@ -166,9 +166,9 @@ public void register(Consumer registry) {
.shape("aba", "cdc", "aea")
.bind('a', Material.IRON_BLOCK, 1)
.bind('b', Material.BLAST_FURNACE, 1)
- .bind('c', ItemRegistry.getItem("ENCHANTED_COAL"), 2)
+ .bind('c', ItemRegistry.get("ENCHANTED_COAL"), 2)
.bind('d', Material.LAVA_BUCKET, 1)
- .bind('e', ItemRegistry.getItem("BLIGHTED_WORKBENCH"), 1)
+ .bind('e', ItemRegistry.get("BLIGHTED_WORKBENCH"), 1)
.build();
BlightedRecipe magmaRodRecipe = shapedRecipe("MAGMA_ROD", 1)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/NetherMaterialRecipes.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/NetherMaterialRecipes.java
index c90f668b..e7212971 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/NetherMaterialRecipes.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/recipes/NetherMaterialRecipes.java
@@ -57,7 +57,7 @@ public void register(Consumer registry) {
.bind('i', Material.NETHERRACK, 12)
.build();
- registry.accept(enchantedGhastTearRecipe);
+ registry.accept(enchantedGhastTearRecipe);
registry.accept(enchantedMagmaCreamRecipe);
registry.accept(enchantedQuartzRecipe);
registry.accept(enchantedBlazePowderRecipe);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/rituals/AncientRituals.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/rituals/AncientRituals.java
index 5eab4228..970c47fd 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/rituals/AncientRituals.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/rituals/AncientRituals.java
@@ -1,6 +1,6 @@
package fr.moussax.blightedSMP.content.rituals;
-import fr.moussax.blightedSMP.content.entities.Illusioner;
+import fr.moussax.blightedSMP.content.entities.powerful.Illusioner;
import fr.moussax.blightedSMP.engine.entities.rituals.AncientRitual;
import fr.moussax.blightedSMP.registry.RegistryModule;
import java.util.function.Consumer;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/utils/ai/EndermanAI.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/utils/ai/EndermanAI.java
index c38e4d1e..5ca2c53c 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/utils/ai/EndermanAI.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/utils/ai/EndermanAI.java
@@ -4,7 +4,7 @@
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
import net.minecraft.world.entity.ai.goal.RandomStrollGoal;
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
-import net.minecraft.world.entity.monster.EnderMan;
+import net.minecraft.world.entity.monster.Enderman;
import net.minecraft.world.entity.player.Player;
import org.bukkit.craftbukkit.entity.CraftMob;
import org.bukkit.entity.LivingEntity;
@@ -16,7 +16,7 @@ private EndermanAI() {
public static void init(LivingEntity spawned) {
if (!(spawned instanceof CraftMob craftMob)) return;
- EnderMan nmsEnderman = (EnderMan) craftMob.getHandle();
+ Enderman nmsEnderman = (Enderman) craftMob.getHandle();
nmsEnderman.goalSelector.removeAllGoals(goal -> true);
nmsEnderman.targetSelector.removeAllGoals(goal -> true);
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
index bd771b66..3c5fcf1a 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/entities/BlightedEntity.java
@@ -831,16 +831,16 @@ public void syncAttachments() {
double zPrime = baseLocation.getZ() + (offset.getX() * sin + offset.getZ() * cos);
double yPrime = baseLocation.getY() + offset.getY();
- Location currentLoc = attachedEntity.getLocation();
- float targetYaw = attachment.syncYaw() ? baseLocation.getYaw() : currentLoc.getYaw();
- float targetPitch = attachment.syncPitch() ? baseLocation.getPitch() : currentLoc.getPitch();
-
- if (currentLoc.getWorld() == baseLocation.getWorld()
- && Math.abs(currentLoc.getX() - xPrime) < 0.001
- && Math.abs(currentLoc.getY() - yPrime) < 0.001
- && Math.abs(currentLoc.getZ() - zPrime) < 0.001
- && Math.abs(currentLoc.getYaw() - targetYaw) < 0.1f
- && Math.abs(currentLoc.getPitch() - targetPitch) < 0.1f) {
+ Location currentLocation = attachedEntity.getLocation();
+ float targetYaw = attachment.syncYaw() ? baseLocation.getYaw() : currentLocation.getYaw();
+ float targetPitch = attachment.syncPitch() ? baseLocation.getPitch() : currentLocation.getPitch();
+
+ if (currentLocation.getWorld() == baseLocation.getWorld()
+ && Math.abs(currentLocation.getX() - xPrime) < 0.001
+ && Math.abs(currentLocation.getY() - yPrime) < 0.001
+ && Math.abs(currentLocation.getZ() - zPrime) < 0.001
+ && Math.abs(currentLocation.getYaw() - targetYaw) < 0.1f
+ && Math.abs(currentLocation.getPitch() - targetPitch) < 0.1f) {
continue;
}
From 2b04dbeb56838b4f95dcd8267fee2a3b00b7cee5 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:25:59 +0200
Subject: [PATCH 24/31] refactor(bedrock): add primitive custom model data
overload and CommandSender message target
- Add setCustomModelData(int) overload to ItemBuilder to avoid boxing.
- Add send(CommandSender) overload to InteractiveMessage for non-player targets.
---
.../bedrock/text/InteractiveMessage.java | 17 +++++++++++++++++
.../fr/moussax/bedrock/utils/ItemBuilder.java | 13 +++++++++++--
2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/text/InteractiveMessage.java b/bedrock/src/main/java/fr/moussax/bedrock/text/InteractiveMessage.java
index a5689d61..f733270a 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/text/InteractiveMessage.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/text/InteractiveMessage.java
@@ -6,6 +6,7 @@
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
+import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
@@ -120,6 +121,22 @@ public void send(@NonNull Player player) {
player.spigot().sendMessage(root);
}
+ /**
+ * Sends the message to a command sender.
+ *
+ * If the sender is a {@link Player}, rich Bungee components with click/hover actions are delivered.
+ * Otherwise, plain text is sent.
+ *
+ * @param sender the recipient
+ */
+ public void send(@NonNull CommandSender sender) {
+ if (sender instanceof Player player) {
+ send(player);
+ } else {
+ sender.sendMessage(root.toLegacyText());
+ }
+ }
+
/**
* Builds the message as Bungee chat components.
*
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/utils/ItemBuilder.java b/bedrock/src/main/java/fr/moussax/bedrock/utils/ItemBuilder.java
index 1b5c24f9..6444c9c7 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/utils/ItemBuilder.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/utils/ItemBuilder.java
@@ -435,10 +435,19 @@ public ItemBuilder setCustomModelData(@Nullable Integer data) {
return this;
}
+ return setCustomModelData(data.intValue());
+ }
+
+ /**
+ * Sets the item's custom model data.
+ *
+ * @param data the custom model data value
+ * @return this builder
+ */
+ public ItemBuilder setCustomModelData(int data) {
CustomModelDataComponent component = itemMeta.getCustomModelDataComponent();
- component.setFloats(List.of(data.floatValue()));
+ component.setFloats(List.of((float) data));
itemMeta.setCustomModelDataComponent(component);
-
return this;
}
From 1f57ce6ca9191ea048cbe5da86d964185692806f Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:26:00 +0200
Subject: [PATCH 25/31] refactor(mod): synchronize IP ban cache removal and
ensure database shutdown safety
- Synchronize IP_BAN removal in PunishmentManager active ban cache.
- Log SQLite close exceptions in PluginDatabase without throwing during teardown.
---
.../java/fr/moussax/blightedMod/database/PluginDatabase.java | 3 +--
.../blightedMod/moderator/punishments/PunishmentManager.java | 4 ++--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/blighted-mod/src/main/java/fr/moussax/blightedMod/database/PluginDatabase.java b/blighted-mod/src/main/java/fr/moussax/blightedMod/database/PluginDatabase.java
index 077edfc1..9174a1d1 100644
--- a/blighted-mod/src/main/java/fr/moussax/blightedMod/database/PluginDatabase.java
+++ b/blighted-mod/src/main/java/fr/moussax/blightedMod/database/PluginDatabase.java
@@ -25,8 +25,7 @@ public void closeConnection() {
connection.close();
}
} catch (SQLException exception) {
- Log.error("PluginDatabase", exception.getMessage());
- throw new RuntimeException("Unable to close the database connection", exception);
+ Log.error("PluginDatabase", "Failed to close database connection: " + exception.getMessage());
}
}
}
diff --git a/blighted-mod/src/main/java/fr/moussax/blightedMod/moderator/punishments/PunishmentManager.java b/blighted-mod/src/main/java/fr/moussax/blightedMod/moderator/punishments/PunishmentManager.java
index ad63c4b4..3703ea73 100644
--- a/blighted-mod/src/main/java/fr/moussax/blightedMod/moderator/punishments/PunishmentManager.java
+++ b/blighted-mod/src/main/java/fr/moussax/blightedMod/moderator/punishments/PunishmentManager.java
@@ -119,7 +119,7 @@ public void removePunishment(UUID playerUuid, PunishmentData.PunishmentType type
if (type == PunishmentData.PunishmentType.MUTE) {
activeMutedPlayers.remove(playerUuid);
- } else if (type == PunishmentData.PunishmentType.BAN) {
+ } else if (type == PunishmentData.PunishmentType.BAN || type == PunishmentData.PunishmentType.IP_BAN) {
activeBannedPlayers.remove(playerUuid);
}
} catch (SQLException exception) {
@@ -186,7 +186,7 @@ public PunishmentData getActivePunishment(UUID playerUuid, PunishmentData.Punish
deactivatePunishment(punishment.id());
if (type == PunishmentData.PunishmentType.MUTE) {
activeMutedPlayers.remove(playerUuid);
- } else if (type == PunishmentData.PunishmentType.BAN) {
+ } else if (type == PunishmentData.PunishmentType.BAN || type == PunishmentData.PunishmentType.IP_BAN) {
activeBannedPlayers.remove(playerUuid);
}
return null;
From cdbabacb2f4a3d467a8734fb4511686c84d525f0 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:30:46 +0200
Subject: [PATCH 26/31] refactor(smp): enforce null check in
ShapelessRecipeBuilder and simplify block place listener
- Add Objects.requireNonNull validation for result item in ShapelessRecipeBuilder.
- Remove redundant hasItemMeta check before meta null check in BlightedBlockListener.
---
.../blightedSMP/engine/items/blocks/BlightedBlockListener.java | 1 -
.../items/recipes/crafting/builder/ShapelessRecipeBuilder.java | 3 ++-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
index 24a44d36..3c09b61f 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/blocks/BlightedBlockListener.java
@@ -58,7 +58,6 @@ private String getBlockId(Block block) {
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
ItemStack item = event.getItemInHand();
- if (!item.hasItemMeta()) return;
ItemMeta meta = item.getItemMeta();
if (meta == null) return;
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
index 6040856f..2a6ceba6 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/recipes/crafting/builder/ShapelessRecipeBuilder.java
@@ -8,6 +8,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Fluent builder for creating {@link BlightedShapelessRecipe} instances.
@@ -24,7 +25,7 @@ public final class ShapelessRecipeBuilder {
private CraftingObject attributeSource = null;
private ShapelessRecipeBuilder(BlightedItem result, int amount) {
- this.result = result;
+ this.result = Objects.requireNonNull(result, "result");
this.amount = amount;
}
From c99af48fec8b9ed73d19193f821973839f33883c Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:37:47 +0200
Subject: [PATCH 27/31] fix(sign): initialize SignBlockEntity tile entity
editor state for Spigot 26.3
- Construct and transmit SignBlockEntity tile entity update packet with allowedPlayerEditor set.
- Restore block state and tile entity state when completing sign input session in SignInputManager.
---
.../bedrock/ui/sign/SignInputManager.java | 20 +++++++---
.../bedrock/ui/sign/SignInputMenu.java | 37 ++++++++++++++-----
2 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputManager.java b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputManager.java
index eff617bd..b75fd242 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputManager.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputManager.java
@@ -2,8 +2,10 @@
import fr.moussax.bedrock.scheduling.PluginContext;
import net.minecraft.core.BlockPos;
+import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.entity.CraftPlayer;
@@ -29,7 +31,7 @@ private record Session(SignInputMenu menu, BlockPos position) {
* Registers an active sign input session for a player.
*
* @param PlayerId player unique identifier
- * @param menu sign input menu handling the session
+ * @param menu sign input menu handling the session
* @param position temporary sign position
*/
static void register(UUID PlayerId, SignInputMenu menu, BlockPos position) {
@@ -43,7 +45,7 @@ static void register(UUID PlayerId, SignInputMenu menu, BlockPos position) {
* invoked.
*
* @param player player who submitted the input
- * @param lines submitted sign lines
+ * @param lines submitted sign lines
*/
public static void handleSignUpdate(Player player, String[] lines) {
Session session = sessions.remove(player.getUniqueId());
@@ -54,11 +56,19 @@ public static void handleSignUpdate(Player player, String[] lines) {
BlockState actualState = nmsPlayer.level().getBlockState(session.position);
nmsPlayer.connection.send(new ClientboundBlockUpdatePacket(session.position, actualState));
+ BlockEntity actualTile = nmsPlayer.level().getBlockEntity(session.position);
+ if (actualTile != null) {
+ Packet> updatePacket = actualTile.getUpdatePacket();
+ if (updatePacket != null) {
+ nmsPlayer.connection.send(updatePacket);
+ }
+ }
+
Bukkit.getScheduler().runTask(PluginContext.get(), () -> {
- if (player.isOnline()) {
- session.menu().handleComplete(player, lines);
+ if (player.isOnline()) {
+ session.menu().handleComplete(player, lines);
+ }
}
- }
);
}
diff --git a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java
index 4c1b53a0..e34e8129 100644
--- a/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java
+++ b/bedrock/src/main/java/fr/moussax/bedrock/ui/sign/SignInputMenu.java
@@ -2,12 +2,18 @@
import fr.moussax.bedrock.scheduling.PluginContext;
import net.minecraft.core.BlockPos;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket;
-import net.minecraft.world.level.block.entity.SignTextSlot;
import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.entity.SignBlockEntity;
+import net.minecraft.world.level.block.entity.SignText;
+import net.minecraft.world.level.block.entity.SignTextSlot;
+import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Bukkit;
import org.bukkit.Location;
-import org.bukkit.Material;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NonNull;
@@ -48,23 +54,34 @@ public SignInputMenu(String[] lines, Consumer onComplete, boole
*/
public void open(@NonNull Player player) {
Location location = player.getLocation().clone();
- location.setY(location.getY() + 3);
- player.sendBlockChange(location, Material.PALE_OAK_SIGN.createBlockData());
+ location.setY(location.getY() + 1);
+
+ BlockPos blockPosition = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
+ ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle();
- String[] safeLines = new String[]{"", "", "", ""};
+ BlockState blockState = Blocks.OAK_SIGN.defaultBlockState();
+ nmsPlayer.connection.send(new ClientboundBlockUpdatePacket(blockPosition, blockState));
+
+ SignBlockEntity signTile = new SignBlockEntity(blockPosition, blockState);
+ signTile.setAllowedPlayerEditor(player.getUniqueId());
+ signTile.setWaxed(false);
+
+ SignTextSlot slot = frontSide ? SignTextSlot.FRONT : SignTextSlot.BACK;
+ SignText.Mutable mutableText = SignText.EMPTY.asMutable();
for (int i = 0; i < Math.min(4, lines.length); i++) {
- safeLines[i] = lines[i] != null ? lines[i] : "";
+ String lineText = lines[i] != null ? lines[i] : "";
+ mutableText.setLine(i, Component.literal(lineText));
}
- player.sendSignChange(location, safeLines);
+ signTile.setText(mutableText.asImmutable(), slot);
- BlockPos blockPosition = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
- ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle();
+ ClientboundBlockEntityDataPacket tilePacket = signTile.getUpdatePacket();
+ nmsPlayer.connection.send(tilePacket);
Bukkit.getScheduler().runTaskLater(PluginContext.get(), () -> {
if (!player.isOnline()) {
return;
}
- nmsPlayer.connection.send(new ClientboundOpenSignEditorPacket(blockPosition, frontSide ? SignTextSlot.FRONT : SignTextSlot.BACK));
+ nmsPlayer.connection.send(new ClientboundOpenSignEditorPacket(blockPosition, slot));
SignInputManager.register(player.getUniqueId(), this, blockPosition);
}, 2L);
}
From 4b924a77ddb9f26d7e4fddd1f7d038499f7d508d Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:51:16 +0200
Subject: [PATCH 28/31] fix(smp): enforce vanilla anvil caps, patch ability
damage attribution, and fix Bonemerang duplication
- Cap standard vanilla book merging at vanillaMax while allowing custom over-capped books up to level 10 in UnsafeAnvilListener.
- Scale anvil repair XP cost dynamically for over-capped enchantment tiers.
- Match Hyperion by BlightedItem ID and attribute damager Player in WitherImpactAbility and KnightsSlamAbility.
- Accurately calculate and report total damage dealt in WitherImpactAbility.
- Tag thrown Bonemerang placeholder nugget with PDC key to prevent item duplication bugs.
---
.../items/abilities/BonemerangAbility.java | 51 +++++++++----------
.../items/abilities/KnightsSlamAbility.java | 2 +-
.../items/abilities/WitherImpactAbility.java | 23 +++++----
.../items/listeners/UnsafeAnvilListener.java | 31 ++++++++---
4 files changed, 61 insertions(+), 46 deletions(-)
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java
index cc13bfb9..e52f6b64 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/BonemerangAbility.java
@@ -4,6 +4,7 @@
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.ArmorStand;
@@ -14,6 +15,7 @@
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
@@ -21,6 +23,8 @@
import java.util.Map;
public class BonemerangAbility implements AbilityManager {
+
+ private static final NamespacedKey THROWN_KEY = new NamespacedKey(BlightedSMP.getInstance(), "thrown_bonemerang");
private static final int OUTBOUND_TICKS = 13;
private static final int RETURN_TICKS = 13;
private static final double PROJECTILE_SPEED = 1.16;
@@ -74,20 +78,21 @@ private void reduceStackInHand(Player player, ItemStack hand) {
}
private void setThrownVisualInHand(Player player, ItemStack from) {
- ItemStack nugget = from.clone();
- nugget.setType(Material.IRON_NUGGET);
- var meta = from.getItemMeta();
+ ItemStack nugget = new ItemStack(Material.IRON_NUGGET);
+ var meta = nugget.getItemMeta();
if (meta != null) {
- nugget.setItemMeta(meta.clone());
+ meta.getPersistentDataContainer().set(THROWN_KEY, PersistentDataType.BYTE, (byte) 1);
+ meta.setDisplayName("§7Bonemerang (Thrown...)");
+ nugget.setItemMeta(meta);
}
player.getInventory().setItemInMainHand(nugget);
}
private void launchProjectile(Player player, ItemStack toRestore) {
ArmorStand projectile = player.getWorld().spawn(
- player.getLocation().add(0, SPAWN_HEIGHT_OFFSET, 0),
- ArmorStand.class,
- this::configureArmorStand
+ player.getLocation().add(0, SPAWN_HEIGHT_OFFSET, 0),
+ ArmorStand.class,
+ this::configureArmorStand
);
player.playSound(player.getLocation(), Sound.BLOCK_BONE_BLOCK_BREAK, 2.0f, 1.75f);
@@ -153,17 +158,17 @@ private void configureArmorStand(ArmorStand stand) {
private void updateProjectilePosition(ArmorStand projectile, Player player, Vector direction, boolean returning) {
Vector movement = returning
- ? player.getLocation().subtract(projectile.getLocation()).toVector().normalize().multiply(PROJECTILE_SPEED)
- : direction.clone().multiply(PROJECTILE_SPEED);
+ ? player.getLocation().subtract(projectile.getLocation()).toVector().normalize().multiply(PROJECTILE_SPEED)
+ : direction.clone().multiply(PROJECTILE_SPEED);
projectile.teleport(projectile.getLocation().add(movement));
}
private void updateProjectileRotation(ArmorStand projectile, int tick) {
projectile.setRightArmPose(new EulerAngle(
- 0,
- Math.toRadians(90 + (ROTATION_SPEED * tick)),
- 0
+ 0,
+ Math.toRadians(90 + (ROTATION_SPEED * tick)),
+ 0
));
}
@@ -196,7 +201,7 @@ private void returnItem(Player player, String expectedName, ItemStack original)
Map leftovers = inventory.addItem(original);
if (!leftovers.isEmpty()) {
leftovers.values().forEach(item ->
- player.getWorld().dropItemNaturally(player.getLocation(), item)
+ player.getWorld().dropItemNaturally(player.getLocation(), item)
);
}
}
@@ -204,22 +209,14 @@ private void returnItem(Player player, String expectedName, ItemStack original)
private boolean replaceNuggetWithOriginal(Inventory inventory, ItemStack original) {
for (int i = 0; i < inventory.getSize(); i++) {
ItemStack slot = inventory.getItem(i);
- if (isSameCustomNugget(slot, original)) {
- inventory.setItem(i, original);
- return true;
+ if (slot != null && slot.getType() == Material.IRON_NUGGET && slot.hasItemMeta()) {
+ var meta = slot.getItemMeta();
+ if (meta != null && meta.getPersistentDataContainer().has(THROWN_KEY, PersistentDataType.BYTE)) {
+ inventory.setItem(i, original);
+ return true;
+ }
}
}
return false;
}
-
- private boolean isSameCustomNugget(ItemStack a, ItemStack b) {
- if (a == null || b == null || a.getType() != Material.IRON_NUGGET) {
- return false;
- }
-
- var aMeta = a.getItemMeta();
- var bMeta = b.getItemMeta();
-
- return aMeta != null && aMeta.equals(bMeta);
- }
}
\ No newline at end of file
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java
index db71731c..4d3673ce 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/KnightsSlamAbility.java
@@ -61,7 +61,7 @@ private KnightSword(Location location, BlightedPlayer player) {
for (Entity entity : entities) {
LivingEntity livingEntity = (LivingEntity) entity;
- livingEntity.damage(abilityDamage);
+ livingEntity.damage(abilityDamage, player.getPlayer());
enemies++;
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java
index e27c8877..f9aa3b0f 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/content/items/abilities/WitherImpactAbility.java
@@ -1,9 +1,9 @@
package fr.moussax.blightedSMP.content.items.abilities;
import fr.moussax.blightedSMP.BlightedSMP;
+import fr.moussax.blightedSMP.engine.items.BlightedItem;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityManager;
import fr.moussax.blightedSMP.engine.items.abilities.AbilityType;
-import fr.moussax.blightedSMP.engine.items.registry.ItemRegistry;
import fr.moussax.blightedSMP.engine.player.BlightedPlayer;
import fr.moussax.bedrock.text.Formatter;
import fr.moussax.bedrock.text.Messenger;
@@ -53,12 +53,10 @@ public boolean triggerAbility(PlayerInteractEvent event) {
}
Player player = event.getPlayer();
- ItemStack item = player.getInventory().getItemInMainHand();
if (!isHoldingHyperion(player)) return false;
teleport(player);
- int entitiesDamaged = damageNearbyEntities(player);
- notifyPlayerOfAbilityDamage(player, entitiesDamaged);
+ damageNearbyEntities(player);
if (canUseHealingAbility(player)) {
applyHealingEffect(player);
@@ -68,7 +66,8 @@ public boolean triggerAbility(PlayerInteractEvent event) {
}
private boolean isHoldingHyperion(Player player) {
- return player.getInventory().getItemInMainHand().equals(ItemRegistry.get("HYPERION").toItemStack());
+ BlightedItem blightedItem = BlightedItem.fromItemStack(player.getInventory().getItemInMainHand());
+ return blightedItem != null && "HYPERION".equals(blightedItem.getItemId());
}
private void teleport(Player player) {
@@ -90,22 +89,24 @@ private Location findTeleportDestination(Player player, Vector direction) {
return location.clone().add(direction.clone().multiply(TELEPORT_DISTANCE));
}
- private int damageNearbyEntities(Player origin) {
+ private double damageNearbyEntities(Player origin) {
double damage = MIN_DAMAGE + (Math.random() * (MAX_DAMAGE - MIN_DAMAGE));
+ double totalDamageDealt = 0.0;
int entitiesDamaged = 0;
for (Entity entity : origin.getNearbyEntities(DAMAGE_RANGE, DAMAGE_RANGE, DAMAGE_RANGE)) {
- if (entity instanceof LivingEntity && !(entity instanceof Player)) {
- ((LivingEntity) entity).damage(damage);
+ if (entity instanceof LivingEntity livingEntity && !(entity instanceof Player)) {
+ livingEntity.damage(damage, origin);
+ totalDamageDealt += damage;
entitiesDamaged++;
}
}
- return entitiesDamaged;
+ notifyPlayerOfAbilityDamage(origin, entitiesDamaged, totalDamageDealt);
+ return totalDamageDealt;
}
- private void notifyPlayerOfAbilityDamage(Player player, int entitiesDamaged) {
+ private void notifyPlayerOfAbilityDamage(Player player, int entitiesDamaged, double totalDamage) {
if (entitiesDamaged > 0) {
- double totalDamage = (double) entitiesDamaged * (15000.0D + Math.random() * 135000.0D);
Messenger.inform(player, "Your implosion hit §d" + entitiesDamaged + " §7enem" + (entitiesDamaged > 1 ? "ies" : "y") + " for §d" + Formatter.formatDecimalWithCommas(totalDamage) + " §7damage.");
}
}
diff --git a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/listeners/UnsafeAnvilListener.java b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/listeners/UnsafeAnvilListener.java
index 746cc43d..269fbdeb 100644
--- a/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/listeners/UnsafeAnvilListener.java
+++ b/blighted-smp/src/main/java/fr/moussax/blightedSMP/engine/items/listeners/UnsafeAnvilListener.java
@@ -16,9 +16,11 @@
import java.util.Map;
+@SuppressWarnings("UnstableApiUsage")
public final class UnsafeAnvilListener implements Listener {
private static final int ENCHANTMENT_HARD_CAP = 10;
+ private static final int OVERCAP_XP_COST_PER_TIER = 4;
@EventHandler(priority = EventPriority.HIGH)
public void onPrepareAnvil(PrepareAnvilEvent event) {
@@ -38,11 +40,13 @@ public void onPrepareAnvil(PrepareAnvilEvent event) {
if (resultMeta == null) return;
boolean isResultBook = result.getType() == Material.ENCHANTED_BOOK;
- Map currentEnchants = isResultBook && resultMeta instanceof EnchantmentStorageMeta storageMeta
+ Map currentEnchants = isResultBook
+ && resultMeta instanceof EnchantmentStorageMeta storageMeta
? storageMeta.getStoredEnchants()
: resultMeta.getEnchants();
boolean changed = false;
+ int maxOvercapTier = 0;
for (Map.Entry entry : bookMeta.getStoredEnchants().entrySet()) {
Enchantment enchant = entry.getKey();
@@ -51,14 +55,15 @@ public void onPrepareAnvil(PrepareAnvilEvent event) {
if (!enchant.canEnchantItem(result) && !isResultBook) continue;
int currentLevel = currentEnchants.getOrDefault(enchant, 0);
+ int vanillaMax = enchant.getMaxLevel();
- int targetLevel = (currentLevel == bookLevel && currentLevel != enchant.getMaxLevel())
- ? currentLevel + 1
- : Math.max(currentLevel, bookLevel);
- int finalLevel = Math.min(targetLevel, ENCHANTMENT_HARD_CAP);
-
+ int finalLevel = getFinalLevel(bookLevel, vanillaMax, currentLevel);
if (finalLevel <= currentLevel) continue;
+ if (finalLevel > vanillaMax) {
+ maxOvercapTier = Math.max(maxOvercapTier, finalLevel - vanillaMax);
+ }
+
if (isResultBook && resultMeta instanceof EnchantmentStorageMeta storageMeta) {
storageMeta.addStoredEnchant(enchant, finalLevel, true);
} else {
@@ -83,7 +88,7 @@ public void onPrepareAnvil(PrepareAnvilEvent event) {
int rightRepairCost = rightMeta instanceof Repairable repairable ? repairable.getRepairCost() : 0;
resultRepairable.setRepairCost(leftRepairCost + rightRepairCost + 2);
- int xpCost = Math.max(1, (leftRepairCost + rightRepairCost) + 2);
+ int xpCost = Math.max(1, (leftRepairCost + rightRepairCost) + 2 + (maxOvercapTier * OVERCAP_XP_COST_PER_TIER));
anvilView.setRepairCost(xpCost);
}
@@ -91,6 +96,18 @@ public void onPrepareAnvil(PrepareAnvilEvent event) {
event.setResult(result);
}
+ private static int getFinalLevel(int bookLevel, int vanillaMax, int currentLevel) {
+ int targetLevel;
+ if (bookLevel <= vanillaMax && currentLevel <= vanillaMax) {
+ // Vanilla combining logic capped at standard vanilla max level
+ targetLevel = (currentLevel == bookLevel) ? Math.min(currentLevel + 1, vanillaMax) : Math.max(currentLevel, bookLevel);
+ } else {
+ // Unsafe combining logic for custom over-capped book drops
+ targetLevel = (currentLevel == bookLevel) ? currentLevel + 1 : Math.max(currentLevel, bookLevel);
+ }
+ return Math.min(targetLevel, ENCHANTMENT_HARD_CAP);
+ }
+
private static boolean isCustomNonEquipment(ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) return false;
BlightedItem blightedItem = BlightedItem.fromItemStack(itemStack);
From da8c98cca18121e0fb13a2d2141a883c30d5bf88 Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:58:30 +0200
Subject: [PATCH 29/31] chore: update api version to 26.3 in both plugins
---
blighted-mod/src/main/resources/plugin.yml | 10 +++++-----
blighted-smp/src/main/resources/plugin.yml | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/blighted-mod/src/main/resources/plugin.yml b/blighted-mod/src/main/resources/plugin.yml
index ea659872..f2fc333e 100644
--- a/blighted-mod/src/main/resources/plugin.yml
+++ b/blighted-mod/src/main/resources/plugin.yml
@@ -3,7 +3,7 @@ version: '${version}'
authors: [ MrInspection ]
main: fr.moussax.blightedMod.BlightedMod
-api-version: '26.2'
+api-version: '26.3'
load: STARTUP
commands:
@@ -15,7 +15,7 @@ commands:
permission: blightedmod.moderator
vanish:
description: Toggle vanish mode.
- aliases: [v]
+ aliases: [ v ]
permission: blightedmod.moderator
mute:
description: Mute a player.
@@ -54,7 +54,7 @@ commands:
description: Report a player or message to online moderators.
slowmode:
description: Set or toggle chat slowmode delay in seconds.
- aliases: [setslowmode]
+ aliases: [ setslowmode ]
permission: blightedmod.moderator
reports:
description: View active player reports.
@@ -73,8 +73,8 @@ commands:
permission: blightedmod.moderator
chat:
description: Switch active chat channel (staff, all).
- aliases: [c]
+ aliases: [ c ]
msginspect:
description: Toggle private message inspection (SocialSpy).
- aliases: [spy, socialspy]
+ aliases: [ spy, socialspy ]
permission: blightedmod.moderator
\ No newline at end of file
diff --git a/blighted-smp/src/main/resources/plugin.yml b/blighted-smp/src/main/resources/plugin.yml
index b5c97c38..e1f6d579 100644
--- a/blighted-smp/src/main/resources/plugin.yml
+++ b/blighted-smp/src/main/resources/plugin.yml
@@ -3,7 +3,7 @@ version: '${version}'
authors: [ MrInspection ]
main: fr.moussax.blightedSMP.BlightedSMP
-api-version: '26.2'
+api-version: '26.3'
load: STARTUP
commands:
From 4721961e06c5b4159ac93184f90b07463ca61f8a Mon Sep 17 00:00:00 2001
From: Moussa
Date: Tue, 29 Sep 2026 23:58:40 +0200
Subject: [PATCH 30/31] ci: update java version
---
.github/workflows/maven.yml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 8eaac953..8541251a 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -1,6 +1,6 @@
name: Maven Build
-on: [pull_request]
+on: [ pull_request ]
permissions:
contents: read
@@ -17,10 +17,10 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- - name: Set up JDK 25
+ - name: Set up JDK 26
uses: actions/setup-java@v4
with:
- java-version: '25'
+ java-version: '26'
distribution: 'temurin'
cache: 'maven'
@@ -45,8 +45,8 @@ jobs:
- name: Verify plugin.yml api-version matches target
run: |
- grep -q "api-version: '26.2'" src/main/resources/plugin.yml || {
- echo "::error::plugin.yml api-version doesn't match Spigot target 26.2"; exit 1; }
+ grep -q "api-version: '26.3'" src/main/resources/plugin.yml || {
+ echo "::error::plugin.yml api-version doesn't match Spigot target 26.3"; exit 1; }
- name: Build and Run Tests
run: mvn -B package --file pom.xml
From 9cfc8e2c3b268019a6f3f34108b597e76ce4248b Mon Sep 17 00:00:00 2001
From: Moussa
Date: Wed, 30 Sep 2026 00:05:26 +0200
Subject: [PATCH 31/31] fix
---
.github/workflows/maven.yml | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 8541251a..0228ad0e 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v4
- name: Set up JDK 26
- uses: actions/setup-java@v4
+ uses: actions/setup-java@v5
with:
java-version: '26'
distribution: 'temurin'
@@ -45,8 +45,16 @@ jobs:
- name: Verify plugin.yml api-version matches target
run: |
- grep -q "api-version: '26.3'" src/main/resources/plugin.yml || {
- echo "::error::plugin.yml api-version doesn't match Spigot target 26.3"; exit 1; }
+ found=0
+ for file in $(find . -path "*/src/main/resources/plugin.yml"); do
+ found=1
+ grep -q "api-version: '26.3'" "$file" || {
+ echo "::error::$file api-version doesn't match Spigot target 26.3"; exit 1;
+ }
+ done
+ if [ "$found" -eq 0 ]; then
+ echo "::error::No plugin.yml files found to verify"; exit 1;
+ fi
- name: Build and Run Tests
run: mvn -B package --file pom.xml
@@ -63,5 +71,5 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: BlightedMC-Plugin
- path: target/*.jar
+ path: '**/target/blighted-*.jar'
retention-days: 5
\ No newline at end of file