diff --git a/build.gradle b/build.gradle index 56eda2e..2bc86a3 100644 --- a/build.gradle +++ b/build.gradle @@ -4,14 +4,16 @@ plugins { } group = 'fr.openmc.riftengine' -version = '0.2-SNAPSHOT' +version = '0.3-SNAPSHOT' repositories { mavenCentral() - // * ItemsAdder - maven {url "https://maven.devs.beer/"} // * GeyserMC maven {url "https://repo.opencollab.dev/main/"} + // * PaperMC + maven { url = "https://repo.papermc.io/repository/maven-public/" } + // * ItemsAdder + maven {url "https://maven.devs.beer/"} } dependencies { diff --git a/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java b/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java index c38bd63..9c06133 100644 --- a/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java +++ b/src/main/java/fr/openmc/riftengine/core/RiftRegistry.java @@ -6,7 +6,6 @@ import fr.openmc.core.bootstrap.registries.RegistryContext; import fr.openmc.core.bootstrap.registries.RegistryLoadingType; import fr.openmc.riftengine.core.registry.glyphs.GlyphsRegistry; -import fr.openmc.riftengine.core.registry.mapping.MappingRegistry; import fr.openmc.riftengine.core.registry.scanner.ScannerRegistry; import java.util.ArrayList; @@ -15,16 +14,12 @@ public final class RiftRegistry { // * Registre globaux - public static MappingRegistry MAPPINGS; public static GlyphsRegistry GLYPHS; public static ScannerRegistry SCANNERS; 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 bcbb5df..fdbf74e 100644 --- a/src/main/java/fr/openmc/riftengine/core/converter/ConverterManager.java +++ b/src/main/java/fr/openmc/riftengine/core/converter/ConverterManager.java @@ -1,18 +1,24 @@ package fr.openmc.riftengine.core.converter; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.utils.FilesUtils; import fr.openmc.riftengine.core.RiftConfig; import fr.openmc.riftengine.core.RiftPlugin; +import fr.openmc.riftengine.core.RiftRegistry; import fr.openmc.riftengine.core.converter.writers.PackWriter; import fr.openmc.riftengine.core.converter.writers.glyph.font.FontWriter; import fr.openmc.riftengine.core.converter.writers.glyph.icons.IconsWriter; import fr.openmc.riftengine.core.converter.writers.glyph.icons.SymbolWriter; +import fr.openmc.riftengine.core.converter.writers.items.ItemsMappingWriter; +import fr.openmc.riftengine.core.converter.writers.items.ItemsTextureJsonWriter; +import fr.openmc.riftengine.core.converter.writers.items.ItemsTextureWriter; 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.scanner.items.ItemEntry; import fr.openmc.riftengine.core.utils.ZipUtils; import org.bukkit.plugin.java.JavaPlugin; @@ -38,14 +44,21 @@ public ConverterManager(RiftPlugin plugin) { try { identity = PackIdentity.loadOrCreate(plugin); + List items = RiftRegistry.SCANNERS.ITEMS.scan(itemsAdderContents); writers.addAll(List.of( new IconWriter(), new ManifestWriter(identity), + new TranslationInjector(), new FontWriter(), new ScoreboardUiWriter(config.isHideScoreboardNumberBedrock()), + new IconsWriter(itemsAdderContents), - new SymbolWriter() + new SymbolWriter(), + + new ItemsTextureJsonWriter(items), + new ItemsTextureWriter(items), + new ItemsMappingWriter(items) )); } catch (Exception e) { throw new RuntimeException("Erreur lors d'initialisation du ConverterManager", e); @@ -55,7 +68,7 @@ public ConverterManager(RiftPlugin plugin) { /** * Prends un pack java et le convertit en pack bedrock */ - public Path generateConvertedPack() throws IOException { + public Path generateConvertedPack() throws Exception { Path javaPackPath = getJavaPackPath(RiftPlugin.getInstance()); Path outputDir = plugin.getDataFolder().toPath().resolve("output"); diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/PackWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/PackWriter.java index 494a14b..952f76f 100644 --- a/src/main/java/fr/openmc/riftengine/core/converter/writers/PackWriter.java +++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/PackWriter.java @@ -4,5 +4,5 @@ import java.nio.file.Path; public interface PackWriter { - void write(Path bedrockRootPath, Path javaRootPath) throws IOException; + void write(Path bedrockRootPath, Path javaRootPath) throws Exception; } diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsMappingWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsMappingWriter.java new file mode 100644 index 0000000..a74e178 --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsMappingWriter.java @@ -0,0 +1,77 @@ +package fr.openmc.riftengine.core.converter.writers.items; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import fr.openmc.core.bootstrap.integration.OMCLogger; +import fr.openmc.riftengine.core.RiftPlugin; +import fr.openmc.riftengine.core.RiftRegistry; +import fr.openmc.riftengine.core.converter.writers.PackWriter; +import fr.openmc.riftengine.core.scanner.items.ItemEntry; +import fr.openmc.riftengine.core.utils.PathUtils; +import org.bukkit.Material; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class ItemsMappingWriter implements PackWriter { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + private final List items; + + public ItemsMappingWriter(List items) { + this.items = items; + } + + @Override + public void write(Path bedrockRootPath, Path javaRootPath) throws Exception { + JsonObject root = new JsonObject(); + root.addProperty("format_version", 2); + + Map byMaterial = new HashMap<>(); + + for (ItemEntry item : items) { + JsonObject def = new JsonObject(); + + if (item.getCustomModelData() != null) { + def.addProperty("type", "legacy"); + def.addProperty("custom_model_data", item.getCustomModelData()); + } else { + def.addProperty("type", "definition"); + def.addProperty("model", item.getNamespace() + ":ia_auto/" + item.getKey()); + } + + def.addProperty("bedrock_identifier", item.namespacedId()); + + JsonObject options = new JsonObject(); + options.addProperty("icon", item.namespacedId()); + def.add("bedrock_options", options); + + byMaterial.computeIfAbsent(item.getMaterial().getKey().asString(), _ -> new JsonArray()) + .add(def); + } + + JsonObject itemsSetter = new JsonObject(); + byMaterial.forEach(itemsSetter::add); + root.add("items", itemsSetter); + + Path outputFile = PathUtils.getGeyserPath(RiftPlugin.getInstance().getDataPath()) + .resolve("custom_mappings").resolve("ia-injected.json"); + Files.createDirectories(outputFile.getParent()); + Files.writeString(outputFile, GSON.toJson(root), StandardCharsets.UTF_8); + } + + private ItemEntry getByNamespace(String namespacedId) { + return items.stream(). + filter(item -> item.namespacedId().equals(namespacedId)) + .findFirst().orElse(null); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsTextureJsonWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsTextureJsonWriter.java new file mode 100644 index 0000000..8ff178c --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsTextureJsonWriter.java @@ -0,0 +1,73 @@ +package fr.openmc.riftengine.core.converter.writers.items; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import fr.openmc.core.bootstrap.integration.OMCLogger; +import fr.openmc.riftengine.core.converter.writers.PackWriter; +import fr.openmc.riftengine.core.scanner.items.ItemEntry; +import fr.openmc.riftengine.core.utils.IdentifierUtils; +import fr.openmc.riftengine.core.utils.PathUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.List; +import java.util.Locale; + +public class ItemsTextureJsonWriter implements PackWriter { + private final List items; + + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + public ItemsTextureJsonWriter(List items) { + this.items = items; + } + + @Override + public void write(Path bedrockRootPath, Path javaRootPath) throws IOException { + JsonObject root = new JsonObject(); + + JsonObject textureData = new JsonObject(); + + for (ItemEntry itemEntry : items) { + String resourceId = itemEntry.getBestResourceId(); + String texture = null; + + if (resourceId == null) { + texture = "textures/items/" + itemEntry.getMaterial().name().toLowerCase();; + } else if (resourceId.startsWith("minecraft:")) { + String path = IdentifierUtils.normalizeId(resourceId).split(":", 2)[1]; + texture = IdentifierUtils.toBedrockTexturePath("textures/" + path); + } else { + Path resourcePath = itemEntry.getResourcePath().apply(javaRootPath); + Path reducedPath = resourcePath == null ? null + : PathUtils.getPathFromRoot(resourcePath, "textures"); + if (reducedPath != null) { + texture = IdentifierUtils.toBedrockTexturePath(reducedPath.toString()) + .replaceFirst("\\.[^/.]+$", ""); + } + } + + if (texture == null) { + OMCLogger.warn("Item {} : impossible de déterminer la texture", itemEntry.namespacedId()); + continue; + } + + JsonObject itemData = new JsonObject(); + itemData.addProperty("textures", texture); + textureData.add(itemEntry.namespacedId(), itemData); + } + + root.addProperty("texture_name", "atlas.items"); + root.add("texture_data", textureData); + + Path outputFile = bedrockRootPath.resolve("textures").resolve("item_texture.json"); + Files.createDirectories(outputFile.getParent()); + Files.writeString(outputFile, GSON.toJson(root), StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsTextureWriter.java b/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsTextureWriter.java new file mode 100644 index 0000000..409808f --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/converter/writers/items/ItemsTextureWriter.java @@ -0,0 +1,55 @@ +package fr.openmc.riftengine.core.converter.writers.items; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import fr.openmc.core.bootstrap.integration.OMCLogger; +import fr.openmc.riftengine.core.converter.writers.PackWriter; +import fr.openmc.riftengine.core.scanner.items.ItemEntry; +import fr.openmc.riftengine.core.utils.IdentifierUtils; +import fr.openmc.riftengine.core.utils.PathUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.List; + +public class ItemsTextureWriter implements PackWriter { + private final List items; + + public ItemsTextureWriter(List items) { + this.items = items; + } + + @Override + public void write(Path bedrockRootPath, Path javaRootPath) throws IOException { + for (ItemEntry itemEntry : items) { + String ressouceId = itemEntry.getBestResourceId(); + if (ressouceId == null) { + OMCLogger.warn("Item {} a pas de resource id", itemEntry.namespacedId()); + continue; + } + + if (ressouceId.split(":")[0].equals("minecraft")) continue; + + Path resourcePath = itemEntry.getResourcePath().apply(javaRootPath); + if (resourcePath == null) { + OMCLogger.warn("Item {} a aucune resource (Model ou texture)", itemEntry.namespacedId()); + continue; + } + + Path reducedPath = PathUtils.getPathFromRoot(resourcePath, "textures"); + if (reducedPath == null) { + OMCLogger.warn("Item {} a un Path impossible a réduire {}", itemEntry.namespacedId(), resourcePath.toString()); + continue; + } + + Path outputFile = bedrockRootPath.resolve( + IdentifierUtils.toBedrockTexturePath(reducedPath.toString())); + Files.createDirectories(outputFile.getParent()); + Files.copy(resourcePath, outputFile, StandardCopyOption.REPLACE_EXISTING); + } + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/riftengine/core/registry/mapping/JsonMapping.java b/src/main/java/fr/openmc/riftengine/core/registry/mapping/JsonMapping.java deleted file mode 100644 index f319b9b..0000000 --- a/src/main/java/fr/openmc/riftengine/core/registry/mapping/JsonMapping.java +++ /dev/null @@ -1,65 +0,0 @@ -package fr.openmc.riftengine.core.registry.mapping; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import fr.openmc.core.bootstrap.integration.OMCLogger; -import fr.openmc.riftengine.core.RiftPlugin; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -public abstract class JsonMapping implements Mapping { - private final Map entries = new HashMap<>(); - - /** - * Chemin du fichier de mapping JSON, ex: "mappings/langs/mapping_26_2.json". - * @return Chemin relatif en partant de resources - */ - public abstract String getBaseFileName(); - - @Override - public void load() { - entries.clear(); - mergeFrom(getBaseFileName()); - - OMCLogger.infoFormatted(getClass().getSimpleName() + " chargé avec " + entries.size() + " entrées"); - } - - private void mergeFrom(String fileName) { - try (InputStream is = RiftPlugin.getInstance().getResource(fileName)) { - if (is == null) return; - - try (Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { - JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); - for (String key : json.keySet()) { - entries.put(key, json.get(key).getAsString()); - } - } - } catch (IOException e) { - OMCLogger.errorFormatted("Erreur de lecture du mapping " + fileName + " : " + e.getMessage()); - } - } - - @Override - public Optional resolve(String javaKey) { - return Optional.ofNullable(entries.get(javaKey)); - } - - @Override - public int size() { - return entries.size(); - } - - @Override - public Map asMap() { - return entries; - } - -} diff --git a/src/main/java/fr/openmc/riftengine/core/registry/mapping/Mapping.java b/src/main/java/fr/openmc/riftengine/core/registry/mapping/Mapping.java deleted file mode 100644 index 38690a8..0000000 --- a/src/main/java/fr/openmc/riftengine/core/registry/mapping/Mapping.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.openmc.riftengine.core.registry.mapping; - -import java.util.Map; -import java.util.Optional; - -public interface Mapping { - void load(); - Optional resolve(K javaKey); - int size(); - Map asMap(); - - default Mapping get() { - return this; - } -} diff --git a/src/main/java/fr/openmc/riftengine/core/registry/mapping/MappingRegistry.java b/src/main/java/fr/openmc/riftengine/core/registry/mapping/MappingRegistry.java deleted file mode 100644 index 62a810f..0000000 --- a/src/main/java/fr/openmc/riftengine/core/registry/mapping/MappingRegistry.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.openmc.riftengine.core.registry.mapping; - -import fr.openmc.core.bootstrap.registries.Registry; - -public class MappingRegistry extends Registry> { - // todo: regarder si c'est réelement utile, inutilisé car le systeme initial de translation ds le pack et tt ne marche pas et geyser on deja un support pour ça - - // ** REGISTER MAPPING ** -} \ No newline at end of file diff --git a/src/main/java/fr/openmc/riftengine/core/registry/scanner/ScannerRegistry.java b/src/main/java/fr/openmc/riftengine/core/registry/scanner/ScannerRegistry.java index 0622df0..fe190ee 100644 --- a/src/main/java/fr/openmc/riftengine/core/registry/scanner/ScannerRegistry.java +++ b/src/main/java/fr/openmc/riftengine/core/registry/scanner/ScannerRegistry.java @@ -5,11 +5,15 @@ import fr.openmc.riftengine.core.scanner.general.YamlNamespaceIAScanner; import fr.openmc.riftengine.core.scanner.general.YamlScanner; import fr.openmc.riftengine.core.scanner.icons.IconScanner; +import fr.openmc.riftengine.core.scanner.items.CustomModelDataScanner; +import fr.openmc.riftengine.core.scanner.items.ItemScanner; public class ScannerRegistry extends Registry> implements KeyedRegistry> { public final IconScanner ICONS = register(new IconScanner()); + public final ItemScanner ITEMS = register(new ItemScanner()); + public final CustomModelDataScanner CUSTOM_MODEL_DATA_CACHE = register(new CustomModelDataScanner()); public final YamlNamespaceIAScanner YAML_ITEMSADDER_NAMESPACE = register(new YamlNamespaceIAScanner()); public final YamlScanner YAML = register(new YamlScanner()); diff --git a/src/main/java/fr/openmc/riftengine/core/scanner/items/CustomModelDataScanner.java b/src/main/java/fr/openmc/riftengine/core/scanner/items/CustomModelDataScanner.java new file mode 100644 index 0000000..f0b745d --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/scanner/items/CustomModelDataScanner.java @@ -0,0 +1,54 @@ +package fr.openmc.riftengine.core.scanner.items; + +import fr.openmc.riftengine.core.RiftPlugin; +import fr.openmc.riftengine.core.RiftRegistry; +import fr.openmc.riftengine.core.registry.scanner.AbstractScanner; +import fr.openmc.riftengine.core.utils.PathUtils; +import fr.openmc.riftengine.core.utils.YmlUtils; +import org.bukkit.Material; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Scan le cache des CustomModelData qui sont assignés par ItemsAdder + */ +public class CustomModelDataScanner extends AbstractScanner>, Void> { + private final String CACHE_FILE_NAME = "items_ids_cache.yml"; + + public Map> scan(Void voyd) throws Exception { + Path cmdPath = PathUtils.getItemsAdderPath(RiftPlugin.getInstance().getDataPath()).resolve("storage").resolve(CACHE_FILE_NAME); + + Map root = YmlUtils.loadYml(cmdPath); + Map> mappedCache = new HashMap<>(); + + for (var iterRoot : root.entrySet()) { + String key = iterRoot.getKey(); + Material materialKey = Material.valueOf(key); + + Map value = new HashMap<>(); + + if (!(iterRoot.getValue() instanceof Map valueMap)) continue; + + Map namespacedIdCmdMap = (Map) valueMap; + + for (var entryIdCmd : namespacedIdCmdMap.entrySet()) { + String namespacedId = entryIdCmd.getKey(); + // todo: __manually_handled, qui serait utile lors de l'impl des CustomEmotes et des models par ailleurs + if (namespacedId.startsWith("__")) continue; + + Integer cmd = entryIdCmd.getValue(); + + value.put(namespacedId, cmd); + } + + mappedCache.put(materialKey, value); + } + + return mappedCache; + } +} diff --git a/src/main/java/fr/openmc/riftengine/core/scanner/items/ItemEntry.java b/src/main/java/fr/openmc/riftengine/core/scanner/items/ItemEntry.java new file mode 100644 index 0000000..8affe18 --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/scanner/items/ItemEntry.java @@ -0,0 +1,138 @@ +package fr.openmc.riftengine.core.scanner.items; + +import fr.openmc.riftengine.core.scanner.items.entry.ItemGraphics; +import fr.openmc.riftengine.core.scanner.items.entry.ItemResource; +import fr.openmc.riftengine.core.utils.IdentifierUtils; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Material; + +import java.nio.file.Path; +import java.util.Map; +import java.util.function.Function; + +@Getter +public class ItemEntry { + private final String namespace; + private final String key; + private final Integer customModelData; + private final Material material; + + private final ItemResource resource; + private final ItemGraphics graphics; + private final Function resourcePath; + + private final Path sourceYml; + + private ItemEntry( + String namespace, + String key, + Integer customModelData, + Material material, + + // * Méthodes de création d'items (moderne ou legacy) + ItemResource resource, + ItemGraphics graphics, + Function resourcePath, + + Path sourceYml + ) { + this.namespace = namespace; + this.key = key; + this.customModelData = customModelData; + this.material = material; + this.resource = resource; + this.graphics = graphics; + this.resourcePath = resourcePath; + this.sourceYml = sourceYml; + } + + public static ItemEntry from(Map> cmdCache, Path sourceYml, String namespace, String key, Map data) { + ItemResource itemResource = ItemResource.from(data); + ItemGraphics itemGraphics = ItemGraphics.from(data); + + Material material = getMaterial(itemResource, itemGraphics); + + Integer customModelData = null; + + Map map = cmdCache.get(material); + if (map != null && map.get(namespace + ":" + key) != null) + customModelData = map.get(namespace + ":" + key); + + return new ItemEntry( + namespace, + key, + customModelData, + material, + itemResource, + itemGraphics, + resolvePathFunction(namespace, itemGraphics, itemResource), + sourceYml + ); + } + + public String getBestResourceId() { + if (resource != null) { + if (resource.hasTextures()) + return IdentifierUtils.normalizeId(resource.textures().getFirst(), namespace); + else if (resource.hasModel()) + return IdentifierUtils.normalizeId(resource.model(), namespace); + } + + // * Méthode graphics + if (graphics != null) { + if (graphics.hasModel()) { + return IdentifierUtils.normalizeId(graphics.model(), namespace); + } + if (graphics.hasTexture()) { + return IdentifierUtils.normalizeId(graphics.texture(), namespace); + } + } + + return null; + } + + private static Material getMaterial(ItemResource resource, ItemGraphics graphics) { + Material byDefault = Material.valueOf(ItemResource.DEFAULT_MATERIAL); + Material resourceMaterial = resource.material(); + Material graphicsMaterial = graphics.material(); + + if (resourceMaterial != byDefault) + return resourceMaterial; + if (graphicsMaterial != byDefault) + return graphicsMaterial; + + return byDefault; + } + + private static Function resolvePathFunction(String namespace, ItemGraphics graphics, ItemResource resource) { + // * Méthode legacy + if (resource != null) { + if (resource.hasTextures()) + // todo: support multiple textures + return javaRoot -> IdentifierUtils.resolveTextureId(javaRoot, + IdentifierUtils.normalizeId(resource.textures().getFirst(), namespace)); + else if (resource.hasModel()) + return javaRoot -> IdentifierUtils.resolveModelId(javaRoot, + IdentifierUtils.normalizeId(resource.model(), namespace)); + } + + // * Méthode graphics + if (graphics != null) { + if (graphics.hasModel()) { + return javaRoot -> IdentifierUtils.resolveModelId(javaRoot, + IdentifierUtils.normalizeId(graphics.model(), namespace)); + } + if (graphics.hasTexture()) { + return javaRoot -> IdentifierUtils.resolveTextureId(javaRoot, + IdentifierUtils.normalizeId(graphics.texture(), namespace)); + } + } + + return _ -> null; + } + + public String namespacedId() { + return namespace + ":" + key; + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/riftengine/core/scanner/items/ItemScanner.java b/src/main/java/fr/openmc/riftengine/core/scanner/items/ItemScanner.java new file mode 100644 index 0000000..69b545c --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/scanner/items/ItemScanner.java @@ -0,0 +1,45 @@ +package fr.openmc.riftengine.core.scanner.items; + +import fr.openmc.riftengine.core.RiftRegistry; +import fr.openmc.riftengine.core.registry.scanner.AbstractScanner; +import fr.openmc.riftengine.core.utils.YmlUtils; +import org.bukkit.Material; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Scan tout les items initialisé par ItemsAdder + */ +public class ItemScanner extends AbstractScanner, Path> { + public List scan(Path itemsAdderContentsPath) throws Exception { + if (!Files.isDirectory(itemsAdderContentsPath)) return new ArrayList<>(); + + List ymlFiles = RiftRegistry.SCANNERS.YAML.scan(itemsAdderContentsPath); + + List result = new ArrayList<>(); + + for (Path ymlFile : ymlFiles) { + Map root = YmlUtils.loadYml(ymlFile); + + Object itemsObj = root.get("items"); + if (!(itemsObj instanceof Map itemsMap)) continue; + + String namespace = RiftRegistry.SCANNERS.YAML_ITEMSADDER_NAMESPACE.scan(root); + Map> mappedCache = RiftRegistry.SCANNERS.CUSTOM_MODEL_DATA_CACHE.scan(null); + + for (Map.Entry entry : itemsMap.entrySet()) { + String key = String.valueOf(entry.getKey()); + if (!(entry.getValue() instanceof Map data)) continue; + + result.add(ItemEntry.from(mappedCache, ymlFile, namespace, key, data)); + } + } + + return result; + } +} diff --git a/src/main/java/fr/openmc/riftengine/core/scanner/items/entry/ItemGraphics.java b/src/main/java/fr/openmc/riftengine/core/scanner/items/entry/ItemGraphics.java new file mode 100644 index 0000000..4b405f0 --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/scanner/items/entry/ItemGraphics.java @@ -0,0 +1,40 @@ +package fr.openmc.riftengine.core.scanner.items.entry; + +import fr.openmc.riftengine.core.utils.YmlUtils; +import org.bukkit.Material; + +import java.util.Map; + +public record ItemGraphics( + String texture, + String model, + Material material +) { + public static ItemGraphics from(Map data) { + if (!(data.get("graphics") instanceof Map graphics)) { + return new ItemGraphics(null, null, Material.PAPER); + } + + // todo: supporter textures (pour block, ou bow, fishing rod, ect) + String texture = YmlUtils.getString(graphics.get("texture"), null); + String model = YmlUtils.getString(graphics.get("model"), null); + Material material = Material.valueOf(YmlUtils.getString( + data.get("material"), ItemResource.DEFAULT_MATERIAL).toUpperCase()); + + return new ItemGraphics(texture, model, material); + } + + public boolean hasTexture() { + if (texture == null) return false; + return !texture.isEmpty(); + } + + public boolean hasModel() { + if (model == null) return false; + return !model.isEmpty(); + } + + public boolean isPresent() { + return hasTexture() || hasModel(); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/riftengine/core/scanner/items/entry/ItemResource.java b/src/main/java/fr/openmc/riftengine/core/scanner/items/entry/ItemResource.java new file mode 100644 index 0000000..2c4c203 --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/scanner/items/entry/ItemResource.java @@ -0,0 +1,53 @@ +package fr.openmc.riftengine.core.scanner.items.entry; + +import fr.openmc.riftengine.core.utils.YmlUtils; +import org.bukkit.Material; + +import java.util.List; +import java.util.Map; + +public record ItemResource( + Material material, + boolean generate, + List textures, + String model +) { + public static final String DEFAULT_MATERIAL = "PAPER"; + + public static ItemResource from(Map data) { + Object resourceObj = data.get("resource"); + if (!(resourceObj instanceof Map resource)) + return new ItemResource(Material.valueOf(DEFAULT_MATERIAL), false, List.of(), null); + + Material material = Material.valueOf(YmlUtils.getString( + resource.get("material"), DEFAULT_MATERIAL).toUpperCase()); + + boolean generate = YmlUtils.getBool(resource.get("generate"), false); + + List textures = resource.get("textures") instanceof List list && resource.get("textures") != null + ? list.stream().map(String::valueOf).toList() + : List.of(); + + if (resource.get("textures") == null && resource.get("texture") != null && textures.isEmpty()) + textures = List.of(String.valueOf(resource.get("texture"))); + + if (textures.isEmpty() && resource.get("textures") instanceof String string) + textures = List.of(string); + + String modelPath = resource.get("model_path") != null + ? String.valueOf(resource.get("model_path")) + : null; + + return new ItemResource(material, generate, textures, modelPath); + } + + public boolean hasTextures() { + if (textures == null) return false; + return !textures.isEmpty(); + } + + public boolean hasModel() { + if (model == null) return false; + return !model.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java b/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java index 3f3890f..aaeaea3 100644 --- a/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java +++ b/src/main/java/fr/openmc/riftengine/core/utils/IdentifierUtils.java @@ -52,4 +52,42 @@ public static Path resolveTextureId(Path rootPath, String id) { .resolve("textures") .resolve(texturePath); } + + /** + * Résout un identifiant en un chemin de fichier dans les assets pour les models + */ + public static Path resolveModelId(Path rootPath, String id) { + String normalizedId = normalizeId(id); + String[] split = normalizedId.split(":", 2); + + String namespace; + String modelPath; + + if (split.length == 2) { + namespace = split[0]; + modelPath = split[1]; + } else { + namespace = "minecraft"; + modelPath = split[0]; + } + + if (!modelPath.endsWith(".json")) { + modelPath += ".json"; + } + + return rootPath + .resolve("assets") + .resolve(namespace) + .resolve("models") + .resolve(modelPath); + } + + public static String toBedrockTexturePath(String javaPath) { + if (javaPath.startsWith("textures/item/")) + return "textures/items/" + javaPath.substring("textures/item/".length()); + if (javaPath.startsWith("textures/block/")) + return "textures/blocks/" + javaPath.substring("textures/block/".length()); + + return javaPath; + } } diff --git a/src/main/java/fr/openmc/riftengine/core/utils/PathUtils.java b/src/main/java/fr/openmc/riftengine/core/utils/PathUtils.java new file mode 100644 index 0000000..c4923e5 --- /dev/null +++ b/src/main/java/fr/openmc/riftengine/core/utils/PathUtils.java @@ -0,0 +1,34 @@ +package fr.openmc.riftengine.core.utils; + +import java.io.File; +import java.nio.file.Path; + +public class PathUtils { + public static Path getPathFromRoot(Path path, String rootName) { + Path reducedPath = null; + for (Path iterPath : path) { + if (reducedPath != null) { + reducedPath = reducedPath.resolve(iterPath); + } + + if (reducedPath == null && iterPath.getFileName().toString().equals(rootName)) + reducedPath = iterPath; + + } + return reducedPath; + } + + public static Path getItemsAdderPath(Path dataPath) { + File pluginsDir = dataPath.toFile().getParentFile(); // * root/plugins + File itemsAdderDir = new File(pluginsDir, "ItemsAdder"); // * root/plugins/ItemsAdder + + return itemsAdderDir.toPath(); + } + + public static Path getGeyserPath(Path dataPath) { + File pluginsDir = dataPath.toFile().getParentFile(); // * root/plugins + File geyserDir = new File(pluginsDir, "Geyser-Spigot"); // * root/plugins/Geyser-Spigot + + return geyserDir.toPath(); + } +} diff --git a/src/main/java/fr/openmc/riftengine/core/utils/YmlUtils.java b/src/main/java/fr/openmc/riftengine/core/utils/YmlUtils.java index 7e3f1f5..f3aeb57 100644 --- a/src/main/java/fr/openmc/riftengine/core/utils/YmlUtils.java +++ b/src/main/java/fr/openmc/riftengine/core/utils/YmlUtils.java @@ -17,6 +17,12 @@ public static Map loadYml(Path path) throws IOException { } } + public static String getString(Object obj, String def) { + if (obj == null) return def; + if (obj instanceof String s) return s; + return String.valueOf(obj); + } + public static Integer getInt(Object obj, Integer def) { if (obj == null) return def; if (obj instanceof Number n) return n.intValue();