Skip to content

Commit 3d3909b

Browse files
authored
Feat/better exemple (#5)
* fix: exemples * feat: add zItems hook for exemples * feat: add zItems soft depend * fix: message
1 parent 27fdd1e commit 3d3909b

33 files changed

Lines changed: 1505 additions & 535 deletions

File tree

api/src/main/java/fr/traqueur/crates/api/registries/HooksRegistry.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.traqueur.crates.api.registries;
22

3+
import fr.traqueur.crates.api.CratesPlugin;
34
import fr.traqueur.crates.api.hooks.Hook;
45
import org.bukkit.plugin.java.JavaPlugin;
56

@@ -19,6 +20,6 @@ public interface HooksRegistry extends Registry<String, Hook> {
1920
* @param plugin the JavaPlugin instance
2021
* @param packageName the package name to scan for hooks
2122
*/
22-
void scanPackage(JavaPlugin plugin, String packageName);
23+
void scanPackage(CratesPlugin plugin, String packageName);
2324

2425
}

common/src/main/java/fr/traqueur/crates/models/placedcrates/EntityCrateDisplay.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class EntityCrateDisplay implements CrateDisplay<Entity> {
1717

1818
public EntityCrateDisplay(Location location, String value, float yaw) {
1919
this.location = location;
20-
this.entityType = value.toUpperCase();
20+
this.entityType = value;
2121
this.yaw = yaw;
2222
}
2323

hooks/MythicMobs/src/main/java/fr/traqueur/crates/hooks/mythicmobs/MythicMobCrateDisplay.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.lumine.mythic.bukkit.MythicBukkit;
88
import io.lumine.mythic.core.mobs.ActiveMob;
99
import org.bukkit.Location;
10+
import org.bukkit.entity.Entity;
1011

1112
import java.util.Optional;
1213

@@ -20,22 +21,59 @@ public MythicMobCrateDisplay(Location location, String value, float yaw) {
2021

2122
@Override
2223
public void spawn() {
24+
// Create centered location while preserving yaw and pitch from original location
25+
Location originalLocation = getLocation();
26+
Location centeredLocation = originalLocation.clone().add(0.5, 0, 0.5);
27+
centeredLocation.setYaw(originalLocation.getYaw());
28+
centeredLocation.setPitch(originalLocation.getPitch());
29+
30+
// Remove any existing entity at this location (from previous server session)
31+
// This ensures ModelEngine properly applies the model to a fresh spawn
32+
Entity existingEntity = findExistingMythicEntity(centeredLocation);
33+
if (existingEntity != null) {
34+
// Check if it's an ActiveMob and remove it properly
35+
Optional<ActiveMob> existingActiveMob = MythicBukkit.inst().getMobManager().getActiveMob(existingEntity.getUniqueId());
36+
if (existingActiveMob.isPresent()) {
37+
existingActiveMob.get().remove();
38+
} else {
39+
existingEntity.remove();
40+
}
41+
}
42+
43+
// Always spawn a fresh MythicMob to ensure ModelEngine applies the model correctly
2344
Optional<MythicMob> mythicMobOpt = MythicBukkit.inst().getMobManager().getMythicMob(this.entityType);
2445
if (mythicMobOpt.isEmpty()) {
2546
throw new IllegalArgumentException("MythicMob type not found: " + this.entityType);
2647
}
2748

28-
this.activeMob = mythicMobOpt.get().spawn(BukkitAdapter.adapt(getLocation()), 1);
49+
// Spawn with the centered location that includes the correct yaw
50+
this.activeMob = mythicMobOpt.get().spawn(BukkitAdapter.adapt(centeredLocation), 1);
2951
this.entity = activeMob.getEntity().getBukkitEntity();
3052

31-
this.entity.setRotation(getLocation().getYaw(), 0);
53+
// Apply rotation immediately
54+
this.entity.setRotation(centeredLocation.getYaw(), 0);
3255
this.entity.setInvulnerable(true);
3356
this.entity.setPersistent(true);
3457
this.entity.setGravity(false);
3558

3659
Keys.PLACED_CRATE_ENTITY.set(this.entity.getPersistentDataContainer(), true);
3760
}
3861

62+
private Entity findExistingMythicEntity(Location centeredLocation) {
63+
// Search for entities with the PDC marker in the vicinity
64+
return centeredLocation.getWorld().getNearbyEntities(centeredLocation, 1, 1, 1).stream()
65+
.filter(e -> {
66+
// Check if entity has our marker
67+
if (!Keys.PLACED_CRATE_ENTITY.get(e.getPersistentDataContainer(), false)) {
68+
return false;
69+
}
70+
// Check if this is a MythicMob entity
71+
return MythicBukkit.inst().getMobManager().isMythicMob(e);
72+
})
73+
.findFirst()
74+
.orElse(null);
75+
}
76+
3977
@Override
4078
public void remove() {
4179
if (activeMob != null) {

hooks/zItems/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
repositories {
2+
maven(url = "https://repo.groupez.dev/releases")
3+
maven(url = "https://repo.groupez.dev/snapshots")
4+
}
5+
6+
dependencies {
7+
compileOnly("fr.traqueur:zitems-api:1b9d3e0")
8+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package fr.traqueur.crates.hooks.zitems;
2+
3+
import fr.traqueur.crates.api.annotations.AutoHook;
4+
import fr.traqueur.crates.api.hooks.Hook;
5+
import fr.traqueur.crates.api.registries.ItemsProvidersRegistry;
6+
import fr.traqueur.crates.api.registries.Registry;
7+
import fr.traqueur.items.api.items.Item;
8+
import fr.traqueur.items.api.registries.ItemsRegistry;
9+
10+
@AutoHook("zItems")
11+
public class ZItemsHook implements Hook {
12+
@Override
13+
public void onEnable() {
14+
ItemsProvidersRegistry itemsProvidersRegistry = Registry.get(ItemsProvidersRegistry.class);
15+
itemsProvidersRegistry.register("ItemsAdder", (player, itemId) -> {
16+
ItemsRegistry registry = fr.traqueur.items.api.registries.Registry.get(ItemsRegistry.class);
17+
Item item = registry.getById(itemId);
18+
return item.build(player, 1);
19+
});
20+
}
21+
}

settings.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ file("hooks").listFiles()?.forEach { file ->
2323
println("Include hooks:${file.name}")
2424
include(":hooks:${file.name}")
2525
}
26-
}
26+
}
27+
include("hooks:zItems")

src/main/java/fr/traqueur/crates/managers/ZCratesManager.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ public class ZCratesManager implements CratesManager {
5858
public void init() {
5959
this.getPlugin().registerListener(new CratesListener(this));
6060
this.ensureInventoriesExist();
61-
this.loadAllPlacedCrates();
61+
62+
// Delay placed crates loading to ensure MythicMobs/ModelEngine are fully initialized
63+
// This prevents display issues with custom models on server restart
64+
Bukkit.getScheduler().runTaskLater(this.getPlugin(), () -> {
65+
this.loadAllPlacedCrates();
66+
Logger.debug("Placed crates loaded after initialization delay");
67+
}, 40L); // 2 seconds delay (40 ticks)
6268
}
6369

6470
private static class OpenedCrate {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package fr.traqueur.crates.models.wrappers;
2+
3+
import fr.traqueur.crates.api.Logger;
4+
import org.mozilla.javascript.NativeArray;
5+
6+
/**
7+
* Helper class for JavaScript array conversions.
8+
* Provides utilities to convert JavaScript arrays to Java arrays.
9+
*/
10+
public class ArrayHelper {
11+
12+
/**
13+
* Converts a JavaScript array to a Java int[] array.
14+
* Accepts both JavaScript arrays (NativeArray) and Java int[] arrays.
15+
*
16+
* @param array the array to convert (can be NativeArray or int[])
17+
* @return the converted int[] array, or null if conversion fails
18+
*/
19+
public static int[] toIntArray(Object array) {
20+
if (array == null) {
21+
Logger.warning("Cannot convert null to int array");
22+
return null;
23+
}
24+
25+
// Already a Java int array
26+
if (array instanceof int[] javaArray) {
27+
return javaArray;
28+
}
29+
30+
// JavaScript NativeArray
31+
if (array instanceof NativeArray nativeArray) {
32+
int length = (int) nativeArray.getLength();
33+
int[] result = new int[length];
34+
35+
for (int i = 0; i < length; i++) {
36+
Object element = nativeArray.get(i);
37+
if (element instanceof Number num) {
38+
result[i] = num.intValue();
39+
} else {
40+
Logger.warning("Invalid array element at index {}: {}", i, element);
41+
return null;
42+
}
43+
}
44+
45+
return result;
46+
}
47+
48+
Logger.warning("Cannot convert {} to int array", array.getClass().getName());
49+
return null;
50+
}
51+
}

src/main/java/fr/traqueur/crates/models/wrappers/InventoryWrapper.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,33 +98,38 @@ public void setRandomItem(int slot) {
9898
/**
9999
* Rotates items through the specified slots (shifts them to the right).
100100
* Only rotates slots that are authorized.
101+
* <p>
102+
* Accepts both Java int[] arrays and JavaScript arrays (NativeArray).
103+
* JavaScript arrays will be automatically converted to int[].
101104
*
102-
* @param slots the slot indices to rotate
105+
* @param slots the slot indices to rotate (int[] or JavaScript array)
103106
*/
104-
public void rotateItems(int[] slots) {
105-
if (slots == null || slots.length < 2) {
107+
public void rotateItems(Object slots) {
108+
// Convert to int[] array (handles both Java and JavaScript arrays)
109+
int[] slotArray = ArrayHelper.toIntArray(slots);
110+
if (slotArray == null || slotArray.length < 2) {
106111
return;
107112
}
108113

109114
// Check all slots are authorized
110-
for (int slot : slots) {
115+
for (int slot : slotArray) {
111116
if (!isAuthorized(slot)) {
112117
Logger.warning("Slot " + slot + " is not authorized for rotation");
113118
return;
114119
}
115120
}
116121

117122
// Save the last item
118-
ItemStack lastItem = delegate.getItem(slots[slots.length - 1]);
123+
ItemStack lastItem = delegate.getItem(slotArray[slotArray.length - 1]);
119124

120125
// Shift all items to the right
121-
for (int i = slots.length - 1; i > 0; i--) {
122-
ItemStack item = delegate.getItem(slots[i - 1]);
123-
delegate.setItem(slots[i], item);
126+
for (int i = slotArray.length - 1; i > 0; i--) {
127+
ItemStack item = delegate.getItem(slotArray[i - 1]);
128+
delegate.setItem(slotArray[i], item);
124129
}
125130

126131
// Put the last item at the first position
127-
delegate.setItem(slots[0], lastItem);
132+
delegate.setItem(slotArray[0], lastItem);
128133
}
129134

130135
/**

src/main/java/fr/traqueur/crates/registries/ZAnimationRegistry.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import fr.traqueur.crates.api.models.animations.Animation;
77
import fr.traqueur.crates.api.registries.AnimationsRegistry;
88
import fr.traqueur.crates.engine.ZScriptEngine;
9+
import fr.traqueur.crates.models.wrappers.ArrayHelper;
910
import org.mozilla.javascript.*;
1011

1112
import java.nio.file.Files;
@@ -36,6 +37,10 @@ protected Animation loadFile(Path file) {
3637
// Add the animation registration API
3738
ScriptableObject.putProperty(scope, "animations", Context.javaToJS(registrar, scope));
3839

40+
// Add array helper utility for JavaScript array conversions
41+
ScriptableObject.putProperty(scope, "ArrayHelper",
42+
Context.javaToJS(new ArrayHelper(), scope));
43+
3944
// Execute the script
4045
engine.evaluateFile(scriptContent, file.getFileName().toString(), scope);
4146

0 commit comments

Comments
 (0)