diff --git a/.idea/icon.svg b/.idea/icon.svg
index 8e3aa24..9bf0610 100644
--- a/.idea/icon.svg
+++ b/.idea/icon.svg
@@ -1,7 +1,6 @@
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/OpenMC.jar b/libs/OpenMC.jar
index 54348ff..1b2f6e9 100644
Binary files a/libs/OpenMC.jar and b/libs/OpenMC.jar differ
diff --git a/src/main/java/fr/openmc/riftengine/core/RiftConfig.java b/src/main/java/fr/openmc/riftengine/core/RiftConfig.java
new file mode 100644
index 0000000..9e85bc8
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/RiftConfig.java
@@ -0,0 +1,25 @@
+package fr.openmc.riftengine.core;
+
+import lombok.Getter;
+import org.bukkit.configuration.file.FileConfiguration;
+
+import java.io.IOException;
+
+public class RiftConfig {
+ private final FileConfiguration config;
+
+ public RiftConfig(RiftPlugin plugin, FileConfiguration config) throws IOException {
+ this.config = config;
+
+ plugin.saveDefaultConfig();
+
+ load();
+ }
+
+ @Getter
+ private boolean hideScoreboardNumberBedrock;
+
+ public void load() {
+ this.hideScoreboardNumberBedrock = config.getBoolean("bedrock.hide-scoreboard-number", true);
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/RiftPlugin.java b/src/main/java/fr/openmc/riftengine/core/RiftPlugin.java
index 12159c1..ed81202 100644
--- a/src/main/java/fr/openmc/riftengine/core/RiftPlugin.java
+++ b/src/main/java/fr/openmc/riftengine/core/RiftPlugin.java
@@ -2,6 +2,7 @@
import fr.openmc.core.bootstrap.integration.OMCLogger;
import fr.openmc.riftengine.core.converter.ConverterManager;
+import fr.openmc.riftengine.core.registry.glyphs.GlyphsRegistry;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.plugin.java.JavaPlugin;
@@ -13,6 +14,7 @@
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.option.PriorityOption;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.function.Consumer;
@@ -24,11 +26,21 @@ public class RiftPlugin extends JavaPlugin implements EventRegistrar {
@Setter
private static ResourcePack resourcePack;
+ @Getter
+ private RiftConfig riftConfig;
+
private ConverterManager converterManager;
+ public static final int[] RP_VERSION = new int[] {1,0};
+
@Override
public void onEnable() {
instance = this;
+ try {
+ riftConfig = new RiftConfig(this, this.getConfig());
+ } catch (IOException e) {
+ throw new RuntimeException("Erreur lors de la lecture du fichier config.yml", e);
+ }
// * Registries internal
RiftRegistry.initAll();
@@ -40,7 +52,10 @@ public void onEnable() {
// * Listeners
registerEvent(SessionLoadResourcePacksEvent.class, this::onLoadResourcePacks);
+ GlyphsRegistry glyphsRegistry = RiftRegistry.GLYPHS;
OMCLogger.info("RiftEngine activé!");
+ OMCLogger.infoFormatted(glyphsRegistry.size() + "/" + glyphsRegistry.maxSize() + "glyphs enregistré");
+ OMCLogger.infoFormatted("Glyphs : " + glyphsRegistry.values());
}
@Override
diff --git a/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java b/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java
index 2ae5a2e..a2089db 100644
--- a/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java
+++ b/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java
@@ -1,36 +1,30 @@
package fr.openmc.riftengine.core;
-import fr.openmc.core.bootstrap.features.types.HasListeners;
+
import fr.openmc.core.bootstrap.integration.OMCLogger;
import fr.openmc.core.bootstrap.registries.LifecycleRegistry;
import fr.openmc.core.bootstrap.registries.RegistryContext;
import fr.openmc.core.bootstrap.registries.RegistryLoadingType;
-import fr.openmc.core.features.events.contents.dailyevents.DailyEventsRegistry;
-import fr.openmc.core.features.events.contents.weeklyevents.WeeklyEventsRegistry;
-import fr.openmc.core.registry.ambient.CustomAmbientRegistry;
-import fr.openmc.core.registry.enchantments.CustomEnchantmentRegistry;
-import fr.openmc.core.registry.items.CustomItemRegistry;
-import fr.openmc.core.registry.lootboxes.CustomLootboxRegistry;
-import fr.openmc.core.registry.loottable.CustomLootTableRegistry;
-import fr.openmc.core.registry.mobs.CustomMobRegistry;
+import fr.openmc.riftengine.core.registry.glyphs.GlyphsRegistry;
import fr.openmc.riftengine.core.registry.mapping.MappingRegistry;
-import io.papermc.paper.plugin.bootstrap.BootstrapContext;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-@SuppressWarnings("UnstableApiUsage")
public final class RiftRegistry {
// * Registre globaux
public static MappingRegistry MAPPINGS;
+ public static GlyphsRegistry GLYPHS;
private static final List LOADED = new ArrayList<>();
private static final List ALL = List.of(
new RegistryContext(
() -> MAPPINGS = new MappingRegistry(),
+ RegistryLoadingType.RUNTIME),
+ new RegistryContext(
+ () -> GLYPHS = new GlyphsRegistry(),
RegistryLoadingType.RUNTIME)
);
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/ConverterManager.java b/src/main/java/fr/openmc/riftengine/core/converter/ConverterManager.java
index d50a4cb..acb0aa5 100644
--- a/src/main/java/fr/openmc/riftengine/core/converter/ConverterManager.java
+++ b/src/main/java/fr/openmc/riftengine/core/converter/ConverterManager.java
@@ -1,11 +1,15 @@
package fr.openmc.riftengine.core.converter;
import fr.openmc.core.bootstrap.integration.OMCLogger;
+import fr.openmc.riftengine.core.RiftConfig;
import fr.openmc.riftengine.core.RiftPlugin;
import fr.openmc.riftengine.core.converter.writers.PackWriter;
+import fr.openmc.riftengine.core.converter.writers.font.FontWriter;
+import fr.openmc.riftengine.core.converter.writers.manifest.IconWriter;
import fr.openmc.riftengine.core.converter.writers.manifest.ManifestWriter;
import fr.openmc.riftengine.core.converter.writers.manifest.PackIdentity;
import fr.openmc.riftengine.core.converter.writers.translations.TranslationInjector;
+import fr.openmc.riftengine.core.converter.writers.ui.ScoreboardUiWriter;
import fr.openmc.riftengine.core.utils.ZipUtils;
import org.bukkit.plugin.java.JavaPlugin;
@@ -25,11 +29,16 @@ public class ConverterManager {
public ConverterManager(RiftPlugin plugin) {
this.plugin = plugin;
+ RiftConfig config = plugin.getRiftConfig();
+
try {
identity = PackIdentity.loadOrCreate(plugin);
writers.addAll(List.of(
+ new IconWriter(),
new ManifestWriter(identity),
- new TranslationInjector()
+ new TranslationInjector(),
+ new FontWriter(),
+ new ScoreboardUiWriter(config.isHideScoreboardNumberBedrock())
));
} catch (Exception e) {
throw new RuntimeException("Erreur lors d'initialisation du ConverterManager", e);
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/font/FontChar.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/font/FontChar.java
new file mode 100644
index 0000000..d58d0b1
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/font/FontChar.java
@@ -0,0 +1,36 @@
+package fr.openmc.riftengine.core.converter.writers.font;
+
+import com.google.gson.JsonArray;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FontChar {
+ public record InternalFontChar(int row, int col, int codePoint, String character) {}
+
+ /**
+ * Extrait les char qu'on a dans un JsonArray
+ * @param charsRows JsonArray contenant les chars
+ * @return liste des characteres (row, col, codePoint)
+ */
+ public static List extractCharPositions(JsonArray charsRows) {
+ List result = new ArrayList<>();
+
+ for (int row = 0; row < charsRows.size(); row++) {
+ String rowStr = charsRows.get(row).getAsString();
+ int col = 0;
+ int i = 0;
+ while (i < rowStr.length()) {
+ int codePoint = rowStr.codePointAt(i); // ex U+0061 retournera 97, car 61 hex -> 97 en dec
+ i++;
+
+ if (codePoint != 0) {
+ String character = String.valueOf(Character.toChars(codePoint));
+ result.add(new InternalFontChar(row, col, codePoint, character));
+ }
+ col++;
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/font/FontWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/font/FontWriter.java
new file mode 100644
index 0000000..d83d95f
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/font/FontWriter.java
@@ -0,0 +1,92 @@
+package fr.openmc.riftengine.core.converter.writers.font;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import fr.openmc.riftengine.core.RiftRegistry;
+import fr.openmc.riftengine.core.converter.writers.PackWriter;
+import fr.openmc.riftengine.core.registry.glyphs.types.FontGlyph;
+import fr.openmc.riftengine.core.utils.IdentifierUtils;
+import fr.openmc.riftengine.core.utils.ScanUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.List;
+
+/**
+ * écrit pas réelement dans un dossier fonts dans le resourcepack bedorck,
+ * aucun support de font sur bedrock, donc on passe par les glyphs.
+ * et faut pas oublier de le modifier sur le coté du client
+ */
+public class FontWriter implements PackWriter {
+ @Override
+ public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
+ List fonts = ScanUtils.scanAllPath(javaRootPath, "font");
+
+ for (Path fontFile : fonts) {
+ if (isMinecraftFont(fontFile)) continue;
+ if (!fontFile.getFileName().toString().endsWith(".json")) continue;
+
+ JsonObject fontJson;
+ try (Reader reader = Files.newBufferedReader(fontFile)) {
+ fontJson = JsonParser.parseReader(reader).getAsJsonObject();
+ }
+
+ String fontNamespace = null;
+ String fontId = null;
+ File fontPng = null;
+ JsonArray fontsChar = null;
+ try {
+ for (JsonElement c : fontJson.getAsJsonArray("providers")) {
+ JsonObject provider = c.getAsJsonObject();
+
+ // todo : support les autres providers (space, TTF, ...)
+ if (provider.get("type").getAsString().equals("bitmap")) {
+ String file = IdentifierUtils.normalizeId(provider.get("file").getAsString());
+
+ fontNamespace = file.split(":")[0];
+ fontId = file.split(":")[1]
+ .replace("font/", "")
+ .replace(".png", "");
+ fontPng = javaRootPath
+ .resolve("assets")
+ .resolve(file.split(":")[0])
+ .resolve("textures")
+ .resolve(file.split(":")[1])
+ .toFile();
+ fontsChar = provider.getAsJsonArray("chars");
+ }
+ }
+ } catch (Exception e) {
+ throw new IOException("Erreur lors de la lecture du fichier font " + fontFile, e);
+ }
+
+ if (fontPng == null || fontsChar == null || fontNamespace == null || fontId == null) return;
+
+ List positions = FontChar.extractCharPositions(fontsChar);
+
+ String page = RiftRegistry.GLYPHS.nextGlyphPage();
+
+ for (FontChar.InternalFontChar pos : positions) {
+ String namespace = fontNamespace + ":" + fontId + ":" + pos.character();
+ RiftRegistry.GLYPHS.register(new FontGlyph(namespace, page, pos.row(), pos.col()));
+ }
+
+ String fileName = "glyph_" + page + ".png";
+ Path glyphPath = bedrockRootPath.resolve("font").resolve(fileName);
+ Files.createDirectories(glyphPath.getParent());
+ Files.copy(fontPng.toPath(), glyphPath, StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+
+ private boolean isMinecraftFont(Path fontFile) {
+ Path namespaceDir = fontFile.getParent().getParent();
+ if (namespaceDir == null) return false;
+ return namespaceDir.getFileName().toString().equals("minecraft");
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/IconWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/IconWriter.java
new file mode 100644
index 0000000..8ba6ddb
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/IconWriter.java
@@ -0,0 +1,21 @@
+package fr.openmc.riftengine.core.converter.writers.manifest;
+
+import fr.openmc.riftengine.core.converter.writers.PackWriter;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+public class IconWriter implements PackWriter {
+ @Override
+ public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
+ try (InputStream is = getClass().getResourceAsStream("/pack_icon.png")) {
+ if (is == null) throw new IOException("Resource introuvable : pack_icon.png");
+
+ Files.copy(is, bedrockRootPath.resolve("pack_icon.png"), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/ManifestWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/ManifestWriter.java
index ed66d25..8d6c8a1 100644
--- a/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/ManifestWriter.java
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/ManifestWriter.java
@@ -17,6 +17,8 @@ public ManifestWriter(PackIdentity identity) {
@Override
public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
+ int[] v = identity.version();
+ String versionJson = "[" + v[0] + ", " + v[1] + ", " + v[2] + "]";
String manifest = """
{
"format_version": 2,
@@ -24,18 +26,18 @@ public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
"name": "RiftPack",
"description": "Généré par RiftEngine à partir de celui de Java",
"uuid": "%s",
- "version": [1, 0, 0],
- "min_engine_version": [26, 44, 0]
+ "version": %s,
+ "min_engine_version": [1, 21, 0]
},
"modules": [
{
"type": "resources",
"uuid": "%s",
- "version": [1, 0, 0]
+ "version": %s
}
]
}
- """.formatted(identity.headerUuid(), identity.moduleUuid());
+ """.formatted(identity.headerUuid(), versionJson, identity.moduleUuid(), versionJson);
Files.writeString(bedrockRootPath.resolve("manifest.json"), manifest, StandardCharsets.UTF_8);
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/PackIdentity.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/PackIdentity.java
index 3769f3c..6736c72 100644
--- a/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/PackIdentity.java
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/manifest/PackIdentity.java
@@ -7,42 +7,58 @@
import java.io.IOException;
import java.util.UUID;
+import static fr.openmc.riftengine.core.RiftPlugin.RP_VERSION;
+
public class PackIdentity {
-
+
private final UUID headerUuid;
private final UUID moduleUuid;
-
- private PackIdentity(UUID headerUuid, UUID moduleUuid) {
+ private final int[] version; // * [major, minor, patch]
+
+ private PackIdentity(UUID headerUuid, UUID moduleUuid, int[] version) {
this.headerUuid = headerUuid;
this.moduleUuid = moduleUuid;
+ this.version = version;
}
-
+
public UUID headerUuid() {
return headerUuid;
}
-
+
public UUID moduleUuid() {
return moduleUuid;
}
-
+
+ public int[] version() {
+ return version;
+ }
+
public static PackIdentity loadOrCreate(JavaPlugin plugin) throws IOException {
File file = new File(plugin.getDataFolder(), "pack-identity.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
-
- boolean changed = false;
+
if (!config.contains("header-uuid")) {
config.set("header-uuid", UUID.randomUUID().toString());
- changed = true;
}
if (!config.contains("module-uuid")) {
config.set("module-uuid", UUID.randomUUID().toString());
- changed = true;
}
- if (changed) config.save(file);
-
+
+ int major = config.getInt("version.major", RP_VERSION[0]);
+ int minor = config.getInt("version.minor", RP_VERSION[1]);
+ int patch = config.getInt("version.patch", 0);
+
+ patch++;
+ config.set("version.major", major);
+ config.set("version.minor", minor);
+ config.set("version.patch", patch);
+
+ config.save(file);
+
return new PackIdentity(
- UUID.fromString(config.getString("header-uuid")),
- UUID.fromString(config.getString("module-uuid"))
+ UUID.fromString(config.getString("header-uuid")),
+ UUID.fromString(config.getString("module-uuid")),
+ new int[]{major, minor, patch}
);
}
}
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/translations/TranslationInjector.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/translations/TranslationInjector.java
index 90fd810..691c140 100644
--- a/src/main/java/fr/openmc/riftengine/core/converter/writers/translations/TranslationInjector.java
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/translations/TranslationInjector.java
@@ -2,6 +2,7 @@
import com.google.gson.*;
import fr.openmc.riftengine.core.converter.writers.PackWriter;
+import fr.openmc.riftengine.core.utils.ScanUtils;
import org.geysermc.geyser.api.GeyserApi;
import java.io.IOException;
@@ -14,7 +15,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Stream;
/**
* Pas réelement un pack writer, on mets juste les .json des langs dans plugins/Geyser-Spigot/locales/overrides.
@@ -30,7 +30,7 @@ public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
Files.createDirectories(localesOverrides);
- List locales = scanAllLocalesPath(javaRootPath);
+ List locales = ScanUtils.scanAllPath(javaRootPath, "lang");
Path mergedDirectory = Files.createTempDirectory("merged-locales");
List mergedLocales = mergeLocales(locales, mergedDirectory);
@@ -44,25 +44,6 @@ public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
}
}
- private List scanAllLocalesPath(Path javaRootPath) throws IOException {
- List localesPath = new ArrayList<>();
-
- Path assetsPath = javaRootPath.resolve("assets");
- if (!Files.isDirectory(assetsPath)) return localesPath;
-
- try (Stream namespaces = Files.list(assetsPath)) {
- for (Path namespaceDir : namespaces.filter(Files::isDirectory).toList()) {
- Path langDir = namespaceDir.resolve("lang");
- if (!Files.isDirectory(langDir)) continue;
-
- try (Stream langFiles = Files.list(langDir)) {
- localesPath.addAll(langFiles.filter(Files::isRegularFile).toList());
- }
- }
- }
- return localesPath;
- }
-
private List mergeLocales(List localesPath, Path outputDirectory) throws IOException {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/ui/ScoreboardUiWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/ui/ScoreboardUiWriter.java
new file mode 100644
index 0000000..2059f49
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/ui/ScoreboardUiWriter.java
@@ -0,0 +1,36 @@
+package fr.openmc.riftengine.core.converter.writers.ui;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import fr.openmc.riftengine.core.converter.writers.PackWriter;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ScoreboardUiWriter implements PackWriter {
+ private final boolean hideScoreboardNumberBedrock;
+
+ private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
+
+ public ScoreboardUiWriter(boolean hideScoreboardNumberBedrock) {
+ this.hideScoreboardNumberBedrock = hideScoreboardNumberBedrock;
+ }
+
+ @Override
+ public void write(Path bedrockRootPath, Path javaRootPath) throws IOException {
+ if (!hideScoreboardNumberBedrock) return;
+
+ JsonObject root = new JsonObject();
+
+ JsonObject visible = new JsonObject();
+ visible.addProperty("visible", false);
+ root.add("scoreboard_sidebar_score", visible);
+
+ Path outputFile = bedrockRootPath.resolve("ui").resolve("scoreboards.json");
+ Files.createDirectories(outputFile.getParent());
+ Files.writeString(outputFile, GSON.toJson(root), StandardCharsets.UTF_8);
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/registry/glyphs/Glyph.java b/src/main/java/fr/openmc/riftengine/core/registry/glyphs/Glyph.java
new file mode 100644
index 0000000..e4fd784
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/registry/glyphs/Glyph.java
@@ -0,0 +1,37 @@
+package fr.openmc.riftengine.core.registry.glyphs;
+
+import lombok.Getter;
+
+@Getter
+public abstract class Glyph {
+ private final String namespacedId;
+ private final String page;
+ private final int row;
+ private final int col;
+ private final char bedrockChar;
+
+ public Glyph(String namespacedId, String page, int row, int col) {
+ this.namespacedId = namespacedId;
+ this.page = page;
+ this.row = row;
+ this.col = col;
+
+ this.bedrockChar = buildBedrockChar();
+ }
+
+ private char buildBedrockChar() {
+ int page = Integer.parseInt(this.page, 16);
+ return (char) ((page << 8) | (row * 16 + col));
+ }
+
+ @Override
+ public String toString() {
+ return "Glyph{" +
+ "namespacedId='" + namespacedId +
+ ", page='" + page +
+ ", row=" + row +
+ ", col=" + col +
+ ", bedrockChar=" + String.format("\\u%04x", (int) bedrockChar) +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/openmc/riftengine/core/registry/glyphs/GlyphsRegistry.java b/src/main/java/fr/openmc/riftengine/core/registry/glyphs/GlyphsRegistry.java
new file mode 100644
index 0000000..05a6a07
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/registry/glyphs/GlyphsRegistry.java
@@ -0,0 +1,40 @@
+package fr.openmc.riftengine.core.registry.glyphs;
+
+import fr.openmc.core.bootstrap.registries.KeyedRegistry;
+import fr.openmc.core.bootstrap.registries.Registry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GlyphsRegistry extends Registry
+ implements KeyedRegistry {
+
+ private final List SLOT_GLYPH = new ArrayList<>(List.of("E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
+ "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"));
+ private int nextPageIndex = 0;
+
+ public String nextGlyphPage() {
+ if (nextPageIndex >= SLOT_GLYPH.size()) {
+ throw new IllegalStateException("Plus de page de glyphs disponible (max " + SLOT_GLYPH.size() + " pages atteint).");
+ }
+ return SLOT_GLYPH.get(nextPageIndex++);
+ }
+
+ @Override
+ public String key(Glyph glyph) {
+ return glyph.getNamespacedId();
+ }
+
+ public int size() {
+ return entries.size();
+ }
+
+ /**
+ * Donne la taille maximale du registre, car on a 23 slots de glyph (EO a F8 inclu),
+ * et dans chaque png on a une grille de 16x16
+ * @return 24 * 16 * 16 = 6144
+ */
+ public int maxSize() {
+ return SLOT_GLYPH.size() * 16*16;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/openmc/riftengine/core/registry/glyphs/types/FontGlyph.java b/src/main/java/fr/openmc/riftengine/core/registry/glyphs/types/FontGlyph.java
new file mode 100644
index 0000000..9dbcd1c
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/registry/glyphs/types/FontGlyph.java
@@ -0,0 +1,9 @@
+package fr.openmc.riftengine.core.registry.glyphs.types;
+
+import fr.openmc.riftengine.core.registry.glyphs.Glyph;
+
+public class FontGlyph extends Glyph {
+ public FontGlyph(String namespacedId, String page, int row, int col) {
+ super(namespacedId, page, row, col);
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java b/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java
new file mode 100644
index 0000000..a686ae5
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java
@@ -0,0 +1,14 @@
+package fr.openmc.riftengine.core.utils;
+
+public class IdentifierUtils {
+ /**
+ * Normalise un identifiant (qui n'a pas un namespace devant
+ * @param id l'id (font/default.png, minecraft:font/default.png)
+ * @return l'id final
+ */
+ public static String normalizeId(String id) {
+ if (id.split(":").length == 2) return id;
+
+ return "minecraft:" + id;
+ }
+}
diff --git a/src/main/java/fr/openmc/riftengine/core/utils/ScanUtils.java b/src/main/java/fr/openmc/riftengine/core/utils/ScanUtils.java
new file mode 100644
index 0000000..161da92
--- /dev/null
+++ b/src/main/java/fr/openmc/riftengine/core/utils/ScanUtils.java
@@ -0,0 +1,36 @@
+package fr.openmc.riftengine.core.utils;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+public class ScanUtils {
+ /**
+ * Scanne tous les fichiers d'un resourcepack java, dans un registre spécial
+ * @param javaRootPath la racine du pack java
+ * @param registryName le nom du registre (ex lang, font, ...)
+ * @return la liste des chemins des fichiers
+ * @throws IOException si erreur pdt la lecture
+ */
+ public static List scanAllPath(Path javaRootPath, String registryName) throws IOException {
+ List localesPath = new ArrayList<>();
+
+ Path assetsPath = javaRootPath.resolve("assets");
+ if (!Files.isDirectory(assetsPath)) return localesPath;
+
+ try (Stream namespaces = Files.list(assetsPath)) {
+ for (Path namespaceDir : namespaces.filter(Files::isDirectory).toList()) {
+ Path registryDir = namespaceDir.resolve(registryName);
+ if (!Files.isDirectory(registryDir)) continue;
+
+ try (Stream registryFile = Files.list(registryDir)) {
+ localesPath.addAll(registryFile.filter(Files::isRegularFile).toList());
+ }
+ }
+ }
+ return localesPath;
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..560673c
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,3 @@
+bedrock:
+ hide-scoreboard-number: true
+ hide-shadow-scoreboard: true
\ No newline at end of file
diff --git a/src/main/resources/pack_icon.png b/src/main/resources/pack_icon.png
new file mode 100644
index 0000000..14f74a0
Binary files /dev/null and b/src/main/resources/pack_icon.png differ