9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-25 18:09:27 +00:00

Merge remote-tracking branch 'upstream/dev' into dev

# Conflicts:
#	gradle.properties
This commit is contained in:
jhqwqmc
2025-06-25 04:30:42 +08:00
94 changed files with 2379 additions and 716 deletions

View File

@@ -16,8 +16,6 @@ import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior {
public static final Factory FACTORY = new Factory();

View File

@@ -5,6 +5,7 @@ import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.plugin.locale.MessageConstants;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.bukkit.command.CommandSender;
import org.incendo.cloud.Command;
import org.incendo.cloud.parser.standard.EnumParser;
@@ -75,7 +76,7 @@ public class ReloadCommand extends BukkitCommandFeature<CommandSender> {
} else if (argument == ReloadArgument.ALL) {
RELOAD_PACK_FLAG = true;
try {
plugin().reloadPlugin(plugin().scheduler().async(), r -> plugin().scheduler().sync().run(r), true).thenAcceptAsync(reloadResult -> {
plugin().reloadPlugin(plugin().scheduler().async(), r -> plugin().scheduler().sync().run(r), !VersionHelper.isFolia()).thenAcceptAsync(reloadResult -> {
try {
long time1 = System.currentTimeMillis();
plugin().packManager().generateResourcePack();

View File

@@ -1,92 +1,3 @@
minecraft:note_block:
instrument=harp:
model: "minecraft:block/note_block"
minecraft:tripwire:
attached=true,east=true,north=true,south=true,disarmed=true,west=true,powered=true:
model: "minecraft:block/tripwire_attached_nsew"
minecraft:red_mushroom_block:
down=true,east=true,north=true,south=true,up=true,west=true:
model: "minecraft:block/red_mushroom_block_inventory"
minecraft:brown_mushroom_block:
down=true,east=true,north=true,south=true,up=true,west=true:
model: "minecraft:block/brown_mushroom_block_inventory"
minecraft:mushroom_stem:
down=true,east=true,north=true,south=true,up=true,west=true:
model: "minecraft:block/mushroom_stem_inventory"
minecraft:kelp:
age=0:
model: "minecraft:block/kelp"
minecraft:weeping_vines:
age=0:
model: "minecraft:block/weeping_vines"
minecraft:twisting_vines:
age=0:
model: "minecraft:block/twisting_vines"
minecraft:cave_vines:
age=0,berries=false:
model: "minecraft:block/cave_vines"
age=0,berries=true:
model: "minecraft:block/cave_vines_lit"
minecraft:sugar_cane:
age=0:
model: "minecraft:block/sugar_cane"
minecraft:oak_leaves:
distance=7,persistent=true:
model: "minecraft:block/oak_leaves"
minecraft:acacia_leaves:
distance=7,persistent=true:
model: "minecraft:block/acacia_leaves"
minecraft:jungle_leaves:
distance=7,persistent=true:
model: "minecraft:block/jungle_leaves"
minecraft:birch_leaves:
distance=7,persistent=true:
model: "minecraft:block/birch_leaves"
minecraft:mangrove_leaves:
distance=7,persistent=true:
model: "minecraft:block/mangrove_leaves"
minecraft:cherry_leaves:
distance=7,persistent=true:
model: "minecraft:block/cherry_leaves"
minecraft:dark_oak_leaves:
distance=7,persistent=true:
model: "minecraft:block/dark_oak_leaves"
minecraft:azalea_leaves:
distance=7,persistent=true:
model: "minecraft:block/azalea_leaves"
minecraft:flowering_azalea_leaves:
distance=7,persistent=true:
model: "minecraft:block/flowering_azalea_leaves"
minecraft:spruce_leaves:
distance=7,persistent=true:
model: "minecraft:block/spruce_leaves"
minecraft:pale_oak_leaves:
distance=7,persistent=true:
model: "minecraft:block/pale_oak_leaves"
minecraft:chorus_plant:
down=true,east=true,north=true,south=true,up=true,west=true:
model: "minecraft:block/default_chorus_plant"
minecraft:oak_sapling:
stage=0:
model: "minecraft:block/oak_sapling"
minecraft:birch_sapling:
stage=0:
model: "minecraft:block/birch_sapling"
minecraft:spruce_sapling:
stage=0:
model: "minecraft:block/spruce_sapling"
minecraft:jungle_sapling:
stage=0:
model: "minecraft:block/jungle_sapling"
minecraft:dark_oak_sapling:
stage=0:
model: "minecraft:block/dark_oak_sapling"
minecraft:acacia_sapling:
stage=0:
model: "minecraft:block/acacia_sapling"
minecraft:cherry_sapling:
stage=0:
model: "minecraft:block/cherry_sapling"
minecraft:pale_oak_sapling:
stage=0:
model: "minecraft:block/pale_oak_sapling"
model: "minecraft:block/default_chorus_plant"

View File

@@ -57,6 +57,8 @@ resource-pack:
# Validate if there are any errors in the resource pack, such as missing textures or models
validate:
enable: true
# Define the name of the overlay folders
overlay-format: "ce_overlay_{version}"
supported-version:
min: "1.20"
max: LATEST

View File

@@ -13,8 +13,7 @@ items#gui_head:
translation: 0,8,0
scale: 2,2,2
model:
type: minecraft:head
kind: player
type: minecraft:player_head
default:gui_head_size_4:
material: player_head
custom-model-data: 1001
@@ -29,8 +28,7 @@ items#gui_head:
translation: 9,7,0
scale: 4,4,4
model:
type: minecraft:head
kind: player
type: minecraft:player_head
items#topaz_gears:
default:topaz_rod:
material: fishing_rod

View File

@@ -4,7 +4,7 @@
"description":"CraftEngine",
"supported_formats": {
"min_inclusive": 15,
"max_inclusive": 71
"max_inclusive": 1000
}
}
}

View File

@@ -1,10 +1,10 @@
{
"pack": {
"pack_format": 15,
"description": "CraftEngine Remove Shulker Head for Some Versions",
"description": "Remove Shulker Head for Some Versions",
"supported_formats": {
"min_inclusive": 15,
"max_inclusive": 99
"max_inclusive": 1000
}
},
"overlays": {
@@ -12,9 +12,9 @@
{
"formats": {
"min_inclusive": 24,
"max_inclusive": 99
"max_inclusive": 1000
},
"directory": "1_20_5_assets"
"directory": "1_20_5_remove_shulker_head_overlay"
}
]
}

View File

@@ -0,0 +1,389 @@
# Nicht ändern
lang-version: "${lang_version}"
exception.invalid_syntax: "<red>Ungültige Syntax. Korrekte Syntax: <white><arg:0></white></red>"
exception.invalid_argument: "<red>Ungültiges Argument. Grund: <white><arg:0></white></red>"
exception.invalid_sender: "<red><arg:0> ist nicht berechtigt, diesen Befehl auszuführen. Muss vom Typ <arg:1></red>"
exception.unexpected: "<red>Beim Versuch, diesen Befehl auszuführen, ist ein interner Fehler aufgetreten</red>"
exception.no_permission: "<red>Es tut mir leid, aber Sie haben keine Berechtigung, diesen Befehl auszuführen</red>"
exception.no_such_command: "Unbekannter Befehl."
argument.entity.notfound.player: "<red>Spieler nicht gefunden: <lang:argument.entity.notfound.player></red>"
argument.entity.notfound.entity: "<red>Entität nicht gefunden: <lang:argument.entity.notfound.entity></red>"
argument.parse.failure.time: "<red>'<arg:0>' ist kein gültiges Zeitformat</red>"
argument.parse.failure.material: "<red>'<arg:0>' ist kein gültiger Materialname</red>"
argument.parse.failure.enchantment: "<red>'<arg:0>' ist keine gültige Verzauberung</red>"
argument.parse.failure.offlineplayer: "<red>Kein Spieler für die Eingabe '<arg:0>' gefunden</red>"
argument.parse.failure.player: "<red>Kein Spieler für die Eingabe '<arg:0>' gefunden</red>"
argument.parse.failure.world: "<red>'<arg:0>' ist keine gültige Minecraft-Welt</red>"
argument.parse.failure.location.invalid_format: "<red>'<arg:0>' ist kein gültiger Ort. Erforderliches Format ist '<arg:1> <arg:2> <arg:3></red>"
argument.parse.failure.location.mixed_local_absolute: "<red>Lokale und absolute Koordinaten können nicht gemischt werden. (Entweder alle Koordinaten verwenden '^' oder keine)</red>"
argument.parse.failure.namespacedkey.namespace: "<red>Ungültiger Namespace '<arg:0>'. Muss [a-z0-9._-] sein</red>"
argument.parse.failure.namespacedkey.key: "<red>Ungültiger Schlüssel '<arg:0>'. Muss [a-z0-9/._-] sein</red>"
argument.parse.failure.namespacedkey.need_namespace: "<red>Ungültige Eingabe '<arg:0>', erfordert einen expliziten Namespace</red>"
argument.parse.failure.boolean: "<red>Konntest keinen booleschen Wert aus '<arg:0>' parsen</red>"
argument.parse.failure.number: "<red>'<arg:0>' ist keine gültige Zahl im Bereich von <arg:1> bis <arg:2></red>"
argument.parse.failure.char: "<red>'<arg:0>' ist kein gültiges Zeichen</red>"
argument.parse.failure.string: "<red>'<arg:0>' ist kein gültiger String vom Typ <arg:1></red>"
argument.parse.failure.uuid: "<red>'<arg:0>' ist keine gültige UUID</red>"
argument.parse.failure.enum: "<red>'<arg:0>' ist keiner der folgenden Werte: <arg:1></red>"
argument.parse.failure.regex: "<red>'<arg:0>' stimmt nicht mit '<arg:1>' überein</red>"
argument.parse.failure.flag.unknown: "<red>Unbekanntes Flag '<arg:0>'</red>"
argument.parse.failure.flag.duplicate_flag: "<red>Doppeltes Flag '<arg:0>'</red>"
argument.parse.failure.flag.no_flag_started: "<red>Kein Flag gestartet. Weiß nicht, was mit '<arg:0>' zu tun ist</red>"
argument.parse.failure.flag.missing_argument: "<red>Fehlendes Argument für '<arg:0>'</red>"
argument.parse.failure.flag.no_permission: "<red>Sie haben keine Berechtigung, '<arg:0>' zu verwenden</red>"
argument.parse.failure.color: "<red>'<arg:0>' ist keine gültige Farbe</red>"
argument.parse.failure.duration: "<red>'<arg:0>' ist kein gültiges Zeitdauerformat</red>"
argument.parse.failure.aggregate.missing: "<red>Fehlende Komponente '<arg:0>'</red>"
argument.parse.failure.aggregate.failure: "<red>Ungültige Komponente '<arg:0>': <arg:1></red>"
argument.parse.failure.either: "<red>Konnte <arg:1> oder <arg:2> aus '<arg:0>' nicht auflösen</red>"
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' ist keine benannte Textfarbe</red>"
command.reload.config.success: "<white>Konfigurationen in <green><arg:0></green> ms neu geladen.</white> <gray>(Async: <arg:1>ms | Sync: <arg:2>ms)</gray>"
command.reload.config.failure: "<red>Neuladen der Konfiguration fehlgeschlagen. Überprüfen Sie die Konsolenprotokolle.</red>"
command.reload.pack.success: "<white>Ressourcenpaket in <green><arg:0></green> ms neu geladen.</white>"
command.reload.pack.failure: "<red>Neuladen des Ressourcenpakets fehlgeschlagen. Überprüfen Sie die Konsolenprotokolle.</red>"
command.reload.all.success: "<white>Neu laden in <green><arg:0></green> ms abgeschlossen.</white> <gray>(Async: <arg:1>ms | Sync: <arg:2>ms | Pack: <arg:3>ms)</gray>"
command.reload.all.failure: "<red>Neu laden fehlgeschlagen. Überprüfen Sie die Konsolenprotokolle.</red>"
command.item.get.success: "<white>Sie haben <arg:0> <arg:1> erhalten</white>"
command.item.get.failure.not_exist: "<red><lang:argument.item.id.invalid:'<arg:0>'></red>"
command.item.give.success.single: "<lang:commands.give.success.single:'<arg:0>':'<arg:1>':'<arg:2>'>"
command.item.give.success.multiple: "<lang:commands.give.success.multiple:'<arg:0>':'<arg:1>':'<arg:2>'>"
command.item.give.failure.not_exist: "<red><lang:argument.item.id.invalid:'<arg:0>'></red>"
command.search_recipe.not_found: "<red>Kein Rezept für diesen Gegenstand gefunden</red>"
command.search_usage.not_found: "<red>Keine Verwendung für diesen Gegenstand gefunden</red>"
command.search_recipe.no_item: "<red>Bitte halten Sie einen Gegenstand, bevor Sie diesen Befehl ausführen</red>"
command.search_usage.no_item: "<red>Bitte halten Sie einen Gegenstand, bevor Sie diesen Befehl ausführen</red>"
command.totem_animation.failure.not_totem: "<red>Gegenstand '<arg:0>' ist kein minecraft:totem_of_undying</red>"
command.resource.enable.success: "<white>Ressource <arg:0> aktiviert. Führen Sie <click:run_command:/ce reload all><u>/ce reload all</u></click> aus, um die Änderungen anzuwenden</white>"
command.resource.enable.failure.unknown: "<red>Unbekannte Ressource <arg:0></red>"
command.resource.disable.success: "<white>Ressource <arg:0> deaktiviert. Führen Sie <click:run_command:/ce reload all><u>/ce reload all</u></click> aus, um die Änderungen anzuwenden</white>"
command.resource.disable.failure.unknown: "<red>Unbekannte Ressource <arg:0></red>"
command.resource.list: "<white>Aktivierte Ressourcen(<arg:0>): <green><arg:1></green><newline>Deaktivierte Ressourcen(<arg:2>): <red><arg:3></red></white>"
command.upload.failure.not_supported: "<red>Die aktuelle Hosting-Methode '<arg:0>' unterstützt das Hochladen von Ressourcenpaketen nicht.</red>"
command.upload.on_progress: "<white>Upload-Vorgang gestartet. Überprüfen Sie die Konsole für weitere Informationen.</white>"
command.send_resource_pack.success.single: "<white>Ressourcenpaket an <arg:0> gesendet.</white>"
command.send_resource_pack.success.multiple: "<white>Ressourcenpakete an <arg:0> Spieler gesendet.</white>"
warning.config.pack.duplicated_files: "</red>Duplizierte Dateien gefunden. Bitte beheben Sie diese im Abschnitt 'resource-pack.duplicated-files-handler' in config.yml.</red>"
warning.config.yaml.duplicated_key: "<red>Problem in Datei <arg:0> gefunden - Duplizierter Schlüssel '<arg:1>' in Zeile <arg:2> gefunden, dies kann zu unerwarteten Ergebnissen führen.</red>"
warning.config.type.int: "<yellow>Problem in Datei <arg:0> gefunden - Laden von '<arg:1>' fehlgeschlagen: Kann '<arg:2>' nicht in den Integer-Typ für Option '<arg:3>' umwandeln.</yellow>"
warning.config.type.float: "<yellow>Problem in Datei <arg:0> gefunden - Laden von '<arg:1>' fehlgeschlagen: Kann '<arg:2>' nicht in den Float-Typ für Option '<arg:3>' umwandeln.</yellow>"
warning.config.type.double: "<yellow>Problem in Datei <arg:0> gefunden - Laden von '<arg:1>' fehlgeschlagen: Kann '<arg:2>' nicht in den Double-Typ für Option '<arg:3>' umwandeln.</yellow>"
warning.config.type.quaternionf: "<yellow>Problem in Datei <arg:0> gefunden - Laden von '<arg:1>' fehlgeschlagen: Kann '<arg:2>' nicht in den Quaternionf-Typ für Option '<arg:3>' umwandeln.</yellow>"
warning.config.type.vector3f: "<yellow>Problem in Datei <arg:0> gefunden - Laden von '<arg:1>' fehlgeschlagen: Kann '<arg:2>' nicht in den Vector3f-Typ für Option '<arg:3>' umwandeln.</yellow>"
warning.config.type.boolean: "<yellow>Problem in Datei <arg:0> gefunden - Laden von '<arg:1>' fehlgeschlagen: Kann '<arg:2>' nicht in den Booleschen Typ für Option '<arg:3>' umwandeln.</yellow>"
warning.config.type.snbt.invalid_syntax: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet einen ungültigen SNBT-Syntax '<arg:2>'.</yellow>"
warning.config.number.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'type'-Argument für das Zahlenargument.</yellow>"
warning.config.number.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet einen ungültigen Zahlargumenttyp '<arg:2>'.</yellow>"
warning.config.number.missing_argument: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das Argument für 'number'.</yellow>"
warning.config.number.invalid_format: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet ein ungültiges Zahlenformat '<arg:2>'.</yellow>"
warning.config.number.fixed.missing_value: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'value'-Argument für die 'constant'-Zahl.</yellow>"
warning.config.number.fixed.invalid_value: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet das ungültige 'value'-Argument '<arg:2>' für die 'constant'-Zahl.</yellow>"
warning.config.number.expression.missing_expression: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'expression'-Argument für die 'expression'-Zahl.</yellow>"
warning.config.number.uniform.missing_min: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'min'-Argument für die 'uniform'-Zahl.</yellow>"
warning.config.number.uniform.missing_max: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'max'-Argument für die 'uniform'-Zahl.</yellow>"
warning.config.condition.all_of.missing_terms: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'terms'-Argument für die 'all_of'-Bedingung.</yellow>"
warning.config.condition.all_of.invalid_terms_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' hat eine falsch konfigurierte 'all_of'-Bedingung, 'terms' sollte eine Kartenliste sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.condition.any_of.missing_terms: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'terms'-Argument für die 'any_of'-Bedingung.</yellow>"
warning.config.condition.any_of.invalid_terms_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' hat eine falsch konfigurierte 'any_of'-Bedingung, 'terms' sollte eine Kartenliste sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.condition.inverted.missing_term: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'term'-Argument für die 'inverted'-Bedingung.</yellow>"
warning.config.condition.inverted.invalid_term_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' hat eine falsch konfigurierte 'inverted'-Bedingung, 'term' sollte ein Konfigurationsabschnitt sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.condition.enchantment.missing_predicate: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'predicate'-Argument für die 'enchantment'-Bedingung.</yellow>"
warning.config.condition.enchantment.invalid_predicate: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet ein ungültiges Verzauberungs-'predicate'-Argument '<arg:2>'.</yellow>"
warning.config.condition.match_block_property.missing_properties: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'properties'-Argument für die 'match_block_property'-Bedingung.</yellow>"
warning.config.condition.match_item.missing_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'id'-Argument für die 'match_item'-Bedingung.</yellow>"
warning.config.condition.table_bonus.missing_enchantment: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'enchantment'-Argument für die 'table_bonus'-Bedingung.</yellow>"
warning.config.condition.table_bonus.missing_chances: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'chances'-Argument für die 'table_bonus'-Bedingung.</yellow>"
warning.config.condition.permission.missing_permission: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'permission'-Argument für die 'permission'-Bedingung.</yellow>"
warning.config.condition.string_equals.missing_value1: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'value1'-Argument für die 'string_equals'-Bedingung.</yellow>"
warning.config.condition.string_equals.missing_value2: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'value2'-Argument für die 'string_equals'-Bedingung.</yellow>"
warning.config.condition.string_contains.missing_value1: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'value1'-Argument für die 'string_contains'-Bedingung.</yellow>"
warning.config.condition.string_contains.missing_value2: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'value2'-Argument für die 'string_contains'-Bedingung.</yellow>"
warning.config.condition.string_regex.missing_value: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'value'-Argument für die 'string_regex'-Bedingung.</yellow>"
warning.config.condition.string_regex.missing_regex: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'regex'-Argument für die 'string_regex'-Bedingung.</yellow>"
warning.config.condition.expression.missing_expression: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'expression'-Argument für die 'expression'-Bedingung.</yellow>"
warning.config.condition.is_null.missing_argument: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'argument'-Argument für die 'is_null'-Bedingung.</yellow>"
warning.config.condition.hand.missing_hand: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'hand'-Argument für die 'hand'-Bedingung.</yellow>"
warning.config.condition.hand.invalid_hand: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet ein ungültiges 'hand'-Argument '<arg:2>' für die 'hand'-Bedingung. Erlaubte Handtypen: [<arg:3>]</yellow>"
warning.config.condition.on_cooldown.missing_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'id'-Argument für die 'on_cooldown'-Bedingung.</yellow>"
warning.config.structure.not_section: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' wird als Konfigurationsabschnitt erwartet, ist aber tatsächlich ein(e) '<arg:2>'.</yellow>"
warning.config.image.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Dupliziertes Bild '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.image.missing_height: "<yellow>Problem in Datei <arg:0> gefunden - Dem Bild '<arg:1>' fehlt das erforderliche 'height'-Argument.</yellow>"
warning.config.image.height_ascent_conflict: "<yellow>Problem in Datei <arg:0> gefunden - Das Bild '<arg:1>' verletzt die Bitmap-Bildregel: 'height'-Argument '<arg:2>' sollte nicht niedriger als 'ascent'-Argument '<arg:3>' sein.</yellow>"
warning.config.image.missing_file: "<yellow>Problem in Datei <arg:0> gefunden - Dem Bild '<arg:1>' fehlt das erforderliche 'file'-Argument.</yellow>"
warning.config.image.invalid_file_chars: "<yellow>Problem in Datei <arg:0> gefunden - Das Bild '<arg:1>' hat ein 'file'-Argument '<arg:2>', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.image.invalid_font_chars: "<yellow>Problem in Datei <arg:0> gefunden - Das Bild '<arg:1>' hat ein 'font'-Argument '<arg:2>', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.image.missing_char: "<yellow>Problem in Datei <arg:0> gefunden - Dem Bild '<arg:1>' fehlt das erforderliche 'char'-Argument.</yellow>"
warning.config.image.codepoint_conflict: "<yellow>Problem in Datei <arg:0> gefunden - Das Bild '<arg:1>' verwendet ein Zeichen '<arg:3>(<arg:4>)' in Schriftart <arg:2>, das von einem anderen Bild '<arg:5>' verwendet wurde.</yellow>"
warning.config.image.invalid_codepoint_grid: "<yellow>Problem in Datei <arg:0> gefunden - Bild '<arg:1>' hat ein ungültiges 'chars'-Codepunktgitter.</yellow>"
warning.config.image.invalid_char: "<yellow>Problem in Datei <arg:0> gefunden - Bild '<arg:1>' hat einen Zeichenparameter, der kombinierende Zeichen enthält, was zu einer Bildaufteilung führen kann.</yellow>"
warning.config.image.invalid_hex_value: "<yellow>Problem in Datei <arg:0> gefunden - Das Bild '<arg:1>' verwendet ein Unicode-Zeichen '<arg:2>', das kein gültiger Hexadezimalwert (Basis 16) ist.</yellow>"
warning.config.recipe.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Dupliziertes Rezept '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.recipe.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Rezept '<arg:1>' fehlt das erforderliche 'type'-Argument.</yellow>"
warning.config.recipe.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Das Rezept '<arg:1>' verwendet einen ungültigen Rezepttyp '<arg:2>'.</yellow>"
warning.config.recipe.invalid_item: "<yellow>Problem in Datei <arg:0> gefunden - Das Rezept '<arg:1>' verwendet einen ungültigen Gegenstand '<arg:2>'.</yellow>"
warning.config.recipe.missing_ingredient: "<yellow>Problem in Datei <arg:0> gefunden - Dem Kochrezept '<arg:1>' fehlt das erforderliche 'ingredient'-Argument.</yellow>"
warning.config.recipe.missing_result: "<yellow>Problem in Datei <arg:0> gefunden - Dem Rezept '<arg:1>' fehlt das erforderliche 'result'-Argument.</yellow>"
warning.config.recipe.result.missing_id: "<yellow>Problem in Datei <arg:0> gefunden - Dem Rezept '<arg:1>' fehlt das erforderliche Argument 'id' für das Rezeptresultat.</yellow>"
warning.config.recipe.crafting.invalid_category: "<yellow>Problem in Datei <arg:0> gefunden - Das Herstellungsrezept '<arg:1>' verwendet eine ungültige Kategorie '<arg:2>'. Erlaubte Kategorien: [<arg:3>].</yellow>"
warning.config.recipe.cooking.invalid_category: "<yellow>Problem in Datei <arg:0> gefunden - Das Kochrezept '<arg:1>' verwendet eine ungültige Kategorie '<arg:2>'. Erlaubte Kategorien: [<arg:3>].</yellow>"
warning.config.recipe.shaped.missing_pattern: "<yellow>Problem in Datei <arg:0> gefunden - Dem geformten Rezept '<arg:1>' fehlt das erforderliche Argument 'pattern'.</yellow>"
warning.config.recipe.shaped.invalid_pattern: "<yellow>Problem in Datei <arg:0> gefunden - Das geformte Rezept '<arg:1>' verwendet ein ungültiges Muster '<arg:2>'.</yellow>"
warning.config.recipe.shaped.invalid_symbol: "<yellow>Problem in Datei <arg:0> gefunden - Das geformte Rezept '<arg:1>' verwendet ein ungültiges Symbol '<arg:2>' im Muster.</yellow>"
warning.config.recipe.smithing_transform.post_processor.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Schmiedetransformationsrezept '<arg:1>' fehlt das erforderliche Argument 'type' für einen der Post-Prozessoren.</yellow>"
warning.config.recipe.smithing_transform.post_processor.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Das Schmiedetransformationsrezept '<arg:1>' verwendet einen ungültigen Post-Prozessor-Typ '<arg:2>'.</yellow>"
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "<yellow>Problem in Datei <arg:0> gefunden - Dem Schmiedetransformationsrezept '<arg:1>' fehlt das erforderliche Argument 'components' für die Post-Prozessoren 'keep_components'.</yellow>"
warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "<yellow>Problem in Datei <arg:0> gefunden - Dem Schmiedetransformationsrezept '<arg:1>' fehlt das erforderliche Argument 'tags' für die Post-Prozessoren 'keep_tags'.</yellow>"
warning.config.i18n.unknown_locale: "<yellow>Problem in Datei <arg:0> gefunden - Unbekanntes Gebietsschema '<arg:1>'.</yellow>"
warning.config.template.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Dupliziertes Template '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.template.invalid: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet ein ungültiges Template '<arg:2>'.</yellow>"
warning.config.template.argument.self_increase_int.invalid_range: "<yellow>Problem in Datei <arg:0> gefunden - Das Template '<arg:1>' verwendet einen 'from'-Wert '<arg:2>', der größer ist als der 'to'-Wert '<arg:3>' im 'self_increase_int'-Argument.</yellow>"
warning.config.template.argument.list.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Das Template '<arg:1>' verwendet ein 'list'-Argument, das eine 'List' als Argument erwartet, während das Eingabeargument ein(e) '<arg:2>' ist.</yellow>"
warning.config.template.argument.default_value.invalid_syntax: "<yellow>Problem in Datei <arg:0> gefunden - Das Template '<arg:1>' verwendet einen ungültigen Standardwert '<arg:2>' für das Argument '<arg:3>'.</yellow>"
warning.config.vanilla_loot.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Vanilla-Beute '<arg:1>' fehlt das erforderliche 'type'-Argument.</yellow>"
warning.config.vanilla_loot.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Vanilla-Beute '<arg:1>' verwendet einen ungültigen Typ '<arg:2>'. Erlaubte Typen: [<arg:3>].</yellow>"
warning.config.vanilla_loot.block.invalid_target: "<yellow>Problem in Datei <arg:0> gefunden - Ungültiges Blockziel '<arg:2>' in Vanilla-Beute '<arg:1>'.</yellow>"
warning.config.sound.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Duplizierter Sound '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.sound.missing_sounds: "<yellow>Problem in Datei <arg:0> gefunden - Dem Sound '<arg:1>' fehlt das erforderliche 'sounds'-Argument.</yellow>"
warning.config.sound.missing_name: "<yellow>Problem in Datei <arg:0> gefunden - Dem Sound '<arg:1>' fehlt das erforderliche 'name'-Argument.</yellow>"
warning.config.jukebox_song.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Dupliziertes Jukebox-Lied '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.jukebox_song.missing_sound: "<yellow>Problem in Datei <arg:0> gefunden - Dem Jukebox-Lied '<arg:1>' fehlt das erforderliche 'sound'-Argument.</yellow>"
warning.config.furniture.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Dupliziertes Möbelstück '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.furniture.missing_placement: "<yellow>Problem in Datei <arg:0> gefunden - Dem Möbelstück '<arg:1>' fehlt das erforderliche 'placement'-Argument.</yellow>"
warning.config.furniture.element.missing_item: "<yellow>Problem in Datei <arg:0> gefunden - Dem Möbelstück '<arg:1>' fehlt das erforderliche 'item'-Argument für eines seiner Elemente.</yellow>"
warning.config.furniture.settings.unknown: "<yellow>Problem in Datei <arg:0> gefunden - Das Möbelstück '<arg:1>' verwendet einen unbekannten Einstellungstyp '<arg:2>'.</yellow>"
warning.config.furniture.hitbox.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Das Möbelstück '<arg:1>' verwendet einen ungültigen Hitbox-Typ '<arg:2>'.</yellow>"
warning.config.furniture.hitbox.custom.invalid_entity: "<yellow>Problem in Datei <arg:0> gefunden - Das Möbelstück '<arg:1>' verwendet eine benutzerdefinierte Hitbox mit ungültigem Entitätstyp '<arg:2>'.</yellow>"
warning.config.item.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Duplizierter Gegenstand '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.item.settings.unknown: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen unbekannten Einstellungstyp '<arg:2>'.</yellow>"
warning.config.item.settings.invulnerable.invalid_damage_source: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet eine unbekannte Schadensquelle '<arg:2>'. Erlaubte Quellen: [<arg:3>].</yellow>"
warning.config.item.settings.equippable.missing_slot: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'slot'-Argument für die 'equippable'-Einstellung.</yellow>"
warning.config.item.missing_material: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'material'-Argument.</yellow>"
warning.config.item.invalid_material: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen Materialtyp '<arg:2>'.</yellow>"
warning.config.item.invalid_custom_model_data: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet negative benutzerdefinierte Modelldaten '<arg:2>', die ungültig sind.</yellow>"
warning.config.item.bad_custom_model_data: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet benutzerdefinierte Modelldaten '<arg:2>', die zu groß sind. Es wird empfohlen, einen Wert unter 16.777.216 zu verwenden.</yellow>"
warning.config.item.custom_model_data_conflict: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet benutzerdefinierte Modelldaten '<arg:2>', die bereits von Gegenstand '<arg:3>' belegt sind.</yellow>"
warning.config.item.invalid_component: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen nicht existierenden Komponententyp '<arg:2>'.</yellow>"
warning.config.item.missing_model_id: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'custom-model-data' oder 'item-model'-Argument.</yellow>"
warning.config.item.missing_model: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt der erforderliche 'model'-Abschnitt für die Unterstützung von 1.21.4+-Ressourcenpaketen.</yellow>"
warning.config.item.behavior.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'type'-Argument für sein Gegenstandsverhalten.</yellow>"
warning.config.item.behavior.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen Gegenstandsverhaltenstyp '<arg:2>'.</yellow>"
warning.config.item.behavior.block.missing_block: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'block'-Argument für das 'block_item'-Verhalten.</yellow>"
warning.config.item.behavior.furniture.missing_furniture: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'furniture'-Argument für das 'furniture_item'-Verhalten.</yellow>"
warning.config.item.behavior.liquid_collision.missing_block: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'block'-Argument für das 'liquid_collision_block_item'-Verhalten.</yellow>"
warning.config.item.legacy_model.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'path'-Argument für das Legacy-Modell.</yellow>"
warning.config.item.legacy_model.overrides.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'path'-Argument für Legacy-Modell-Überschreibungen.</yellow>"
warning.config.item.legacy_model.overrides.missing_predicate: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'predicate'-Argument für Legacy-Modell-Überschreibungen.</yellow>"
warning.config.item.legacy_model.cannot_convert: "<yellow>Problem in Datei <arg:0> gefunden - Kann 1.21.4+-Gegenstände für Gegenstand '<arg:1>' nicht in das Legacy-Format konvertieren. Bitte erstellen Sie den Abschnitt 'legacy-model' für diesen Gegenstand manuell.</yellow>"
warning.config.item.model.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen Modelltyp '<arg:2>'.</yellow>"
warning.config.item.model.tint.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'type'-Argument für die Tönung.</yellow>"
warning.config.item.model.tint.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen Tönungstyp '<arg:2>'.</yellow>"
warning.config.item.model.tint.constant.missing_value: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'value'-Argument für die konstante Tönung.</yellow>"
warning.config.item.model.tint.grass.invalid_temp: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet eine ungültige Temperatur '<arg:2>' für die Grastönung, die zwischen 0 und 1 liegen sollte.</yellow>"
warning.config.item.model.tint.grass.invalid_downfall: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen Niederschlag '<arg:2>' für die Grastönung, der zwischen 0 und 1 liegen sollte.</yellow>"
warning.config.item.model.tint.invalid_value: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet eine ungültige Tönung '<arg:2>'.</yellow>"
warning.config.item.model.base.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'path'-Argument für das Modell 'minecraft:model'.</yellow>"
warning.config.item.model.base.invalid_path: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' hat ein ungültiges 'path'-Argument '<arg:2>' für das Modell 'minecraft:model', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.item.model.condition.missing_property: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'property'-Argument für das Modell 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.invalid_property: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet eine ungültige Eigenschaft '<arg:2>' für das Modell 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.missing_on_true: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'on-true'-Argument für das Modell 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.missing_on_false: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'on-false'-Argument für das Modell 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.keybind.missing_keybind: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'keybind'-Argument für die Eigenschaft 'minecraft:keybind_down'.</yellow>"
warning.config.item.model.condition.component.missing_predicate: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'predicate'-Argument für die Eigenschaft 'minecraft:has_component'.</yellow>"
warning.config.item.model.condition.component.missing_value: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'value'-Argument für die Eigenschaft 'minecraft:has_component'.</yellow>"
warning.config.item.model.condition.has_component.missing_component: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'component'-Argument für die Eigenschaft 'minecraft:has_component'.</yellow>"
warning.config.item.model.composite.missing_models: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'models'-Argument für das Modell 'minecraft:composite'.</yellow>"
warning.config.item.model.range_dispatch.missing_property: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'property'-Argument für das Modell 'minecraft:range_dispatch'.</yellow>"
warning.config.item.model.range_dispatch.invalid_property: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet eine ungültige Eigenschaft '<arg:2>' für das Modell 'minecraft:range_dispatch'.</yellow>"
warning.config.item.model.range_dispatch.missing_entries: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'entries'-Argument für das Modell 'minecraft:composite'.</yellow>"
warning.config.item.model.range_dispatch.entry.missing_model: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'model'-Argument für einen der Einträge im Modell 'minecraft:composite'.</yellow>"
warning.config.item.model.range_dispatch.compass.missing_target: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'target'-Argument für die Eigenschaft 'minecraft:compass'.</yellow>"
warning.config.item.model.range_dispatch.time.missing_source: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'source'-Argument für die Eigenschaft 'minecraft:time'.</yellow>"
warning.config.item.model.select.missing_property: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'property'-Argument für das Modell 'minecraft:select'.</yellow>"
warning.config.item.model.select.invalid_property: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet eine ungültige Eigenschaft '<arg:2>' für das Modell 'minecraft:select'.</yellow>"
warning.config.item.model.select.missing_cases: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'cases'-Argument für das Modell 'minecraft:select'.</yellow>"
warning.config.item.model.select.case.missing_when: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'when'-Argument für einen der Fälle im Modell 'minecraft:select'.</yellow>"
warning.config.item.model.select.case.missing_model: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'model'-Argument für einen der Fälle im Modell 'minecraft:select'.</yellow>"
warning.config.item.model.select.component.missing_component: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'component'-Argument für die Eigenschaft 'minecraft:component'.</yellow>"
warning.config.item.model.select.block_state.missing_property: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'block-state-property'-Argument für die Eigenschaft 'minecraft:block_state'.</yellow>"
warning.config.item.model.select.local_time.missing_pattern: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'pattern'-Argument für die Eigenschaft 'minecraft:local_time'.</yellow>"
warning.config.item.model.special.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'type'-Argument für das Modell 'minecraft:special'.</yellow>"
warning.config.item.model.special.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'path'-Argument für das Modell 'minecraft:special'.</yellow>"
warning.config.item.model.special.invalid_path: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' hat ein ungültiges 'path'-Argument '<arg:2>' für das Modell 'minecraft:special', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.item.model.special.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen Typ '<arg:2>' für das Modell 'minecraft:special'.</yellow>"
warning.config.item.model.special.banner.missing_color: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'color'-Argument für das Spezialmodell 'minecraft:banner'.</yellow>"
warning.config.item.model.special.bed.missing_texture: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'texture'-Argument für das Spezialmodell 'minecraft:bed'.</yellow>"
warning.config.item.model.special.sign.missing_wood_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'wood-type'-Argument für das Spezialmodell 'minecraft:hanging_sign'/'minecraft:standing_sign'.</yellow>"
warning.config.item.model.special.sign.missing_texture: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'texture'-Argument für das Spezialmodell 'minecraft:hanging_sign'/'minecraft:standing_sign'.</yellow>"
warning.config.item.model.special.chest.missing_texture: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'texture'-Argument für das Spezialmodell 'minecraft:chest'.</yellow>"
warning.config.item.model.special.chest.invalid_openness: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen 'openness'-Wert '<arg:2>' für das Spezialmodell 'minecraft:chest'. Gültiger Bereich '0~1.'</yellow>"
warning.config.item.model.special.shulker_box.missing_texture: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'texture'-Argument für das Spezialmodell 'minecraft:shulker_box'.</yellow>"
warning.config.item.model.special.shulker_box.invalid_openness: "<yellow>Problem in Datei <arg:0> gefunden - Der Gegenstand '<arg:1>' verwendet einen ungültigen 'openness'-Wert '<arg:2>' für das Spezialmodell 'minecraft:shulker_box'. Gültiger Bereich '0~1.'</yellow>"
warning.config.item.model.special.head.missing_kind: "<yellow>Problem in Datei <arg:0> gefunden - Dem Gegenstand '<arg:1>' fehlt das erforderliche 'kind'-Argument für das Spezialmodell 'minecraft:head'.</yellow>"
warning.config.block.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Duplizierter Block '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.block.missing_state: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'state'-Argument.</yellow>"
warning.config.block.state.property.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'type'-Argument für die Eigenschaft '<arg:2>'.</yellow>"
warning.config.block.state.property.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet das ungültige 'type'-Argument '<arg:2>' für die Eigenschaft '<arg:3>'.</yellow>"
warning.config.block.state.property.integer.invalid_range: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet das ungültige 'range'-Argument '<arg:2>' für die Integer-Eigenschaft '<arg:3>'. Korrekte Syntax: 1~2.</yellow>"
warning.config.block.state.property.invalid_format: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet ein ungültiges Blockzustandsformat '<arg:2>'.</yellow>"
warning.config.block.state.missing_real_id: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'id'-Argument für 'state'. 'id' ist die serverseitige Block-ID, die für jeden Blockzustandstyp eindeutig ist. Wenn Sie einen serverseitigen Block mit 'note_block' und ID 30 erstellen, wäre die echte Block-ID 'craftengine:note_block_30'.</yellow>"
warning.config.block.state.missing_state: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'state'-Argument für 'state'.</yellow>"
warning.config.block.state.missing_properties: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt der erforderliche 'properties'-Abschnitt für 'states'.</yellow>"
warning.config.block.state.missing_appearances: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt der erforderliche 'appearances'-Abschnitt für 'states'.</yellow>"
warning.config.block.state.missing_variants: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt der erforderliche 'variants'-Abschnitt für 'states'.</yellow>"
warning.config.block.state.variant.missing_appearance: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'appearance'-Argument für Variante '<arg:2>'.</yellow>"
warning.config.block.state.variant.invalid_appearance: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' hat einen Fehler, dass die Variante '<arg:2>' ein nicht existierendes Erscheinungsbild '<arg:3>' verwendet.</yellow>"
warning.config.block.state.invalid_vanilla: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen ungültigen Vanilla-Blockzustand '<arg:2>'.</yellow>"
warning.config.block.state.unavailable_vanilla: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen nicht verfügbaren Vanilla-Blockzustand '<arg:2>'. Bitte geben Sie diesen Zustand in mappings.yml frei.</yellow>"
warning.config.block.state.invalid_vanilla_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen Vanilla-Blockzustand '<arg:2>', der den verfügbaren Slot-Bereich '0~<arg:3>' überschreitet.</yellow>"
warning.config.block.state.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen Vanilla-Blockzustand '<arg:2>', der bereits von '<arg:3>' belegt ist.</yellow>"
warning.config.block.state.bind_failed: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' konnte den echten Blockzustand für '<arg:2>' nicht binden, da der Zustand von '<arg:3>' belegt ist.</yellow>"
warning.config.block.state.missing_model: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'model' oder 'models'-Argument.</yellow>"
warning.config.block.state.invalid_real_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen echten Blockzustand '<arg:2>', der den verfügbaren Slot-Bereich '0~<arg:3>' überschreitet. Erwägen Sie, weitere echte Zustände in 'additional-real-blocks.yml' hinzuzufügen, wenn die Slots aufgebraucht sind.</yellow>"
warning.config.block.state.model.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'path'-Option für 'model'.</yellow>"
warning.config.block.state.model.invalid_path: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' hat ein 'path'-Argument '<arg:2>', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.block.settings.unknown: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen unbekannten Einstellungstyp '<arg:2>'.</yellow>"
warning.config.block.behavior.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'type'-Argument für sein Blockverhalten.</yellow>"
warning.config.block.behavior.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen ungültigen Blockverhaltenstyp '<arg:2>'.</yellow>"
warning.config.block.behavior.concrete.missing_solid: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'solid-block'-Option für das 'concrete_block'-Verhalten.</yellow>"
warning.config.block.behavior.crop.missing_age: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'age'-Eigenschaft für das 'crop_block'-Verhalten.</yellow>"
warning.config.block.behavior.sugar_cane.missing_age: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'age'-Eigenschaft für das 'sugar_cane_block'-Verhalten.</yellow>"
warning.config.block.behavior.leaves.missing_persistent: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'persistent'-Eigenschaft für das 'leaves_block'-Verhalten.</yellow>"
warning.config.block.behavior.leaves.missing_distance: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'distance'-Eigenschaft für das 'leaves_block'-Verhalten.</yellow>"
warning.config.block.behavior.lamp.missing_lit: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'lit'-Eigenschaft für das 'lamp_block'-Verhalten.</yellow>"
warning.config.block.behavior.sapling.missing_stage: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'stage'-Eigenschaft für das 'sapling_block'-Verhalten.</yellow>"
warning.config.block.behavior.sapling.missing_feature: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'feature'-Argument für das 'sapling_block'-Verhalten.</yellow>"
warning.config.block.behavior.strippable.missing_stripped: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'stripped'-Argument für das 'strippable_block'-Verhalten.</yellow>"
warning.config.block.behavior.door.missing_half: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'half'-Eigenschaft für das 'door_block'-Verhalten.</yellow>"
warning.config.block.behavior.door.missing_facing: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'facing'-Eigenschaft für das 'door_block'-Verhalten.</yellow>"
warning.config.block.behavior.door.missing_hinge: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'hinge'-Eigenschaft für das 'door_block'-Verhalten.</yellow>"
warning.config.block.behavior.door.missing_open: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'open'-Eigenschaft für das 'door_block'-Verhalten.</yellow>"
warning.config.block.behavior.door.missing_powered: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'powered'-Eigenschaft für das 'door_block'-Verhalten.</yellow>"
warning.config.block.behavior.trapdoor.missing_half: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'half'-Eigenschaft für das 'trapdoor_block'-Verhalten.</yellow>"
warning.config.block.behavior.trapdoor.missing_facing: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'facing'-Eigenschaft für das 'trapdoor_block'-Verhalten.</yellow>"
warning.config.block.behavior.trapdoor.missing_open: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'open'-Eigenschaft für das 'trapdoor_block'-Verhalten.</yellow>"
warning.config.block.behavior.trapdoor.missing_powered: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'powered'-Eigenschaft für das 'trapdoor_block'-Verhalten.</yellow>"
warning.config.block.behavior.stackable.missing_property: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche '<arg:2>'-Eigenschaft für das 'stackable_block'-Verhalten.</yellow>"
warning.config.block.behavior.stackable.missing_items: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'items'-Argument für das 'stackable_block'-Verhalten.</yellow>"
warning.config.block.behavior.fence_gate.missing_facing: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'facing'-Argument für das 'fence_gate_block'-Verhalten.</yellow>"
warning.config.block.behavior.fence_gate.missing_in_wall: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'in_wall'-Argument für das 'fence_gate_block'-Verhalten.</yellow>"
warning.config.block.behavior.fence_gate.missing_open: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'powered'-Argument für das 'fence_gate_block'-Verhalten.</yellow>"
warning.config.block.behavior.fence_gate.missing_powered: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'open'-Argument für das 'fence_gate_block'-Verhalten.</yellow>"
warning.config.block.behavior.trapdoor.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'type'-Eigenschaft für das 'slab_block'-Verhalten.</yellow>"
warning.config.block.behavior.stairs.missing_facing: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'facing'-Eigenschaft für das 'stairs_block'-Verhalten.</yellow>"
warning.config.block.behavior.stairs.missing_half: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'half'-Eigenschaft für das 'stairs_block'-Verhalten.</yellow>"
warning.config.block.behavior.stairs.missing_shape: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'shape'-Eigenschaft für das 'stairs_block'-Verhalten.</yellow>"
warning.config.block.behavior.pressure_plate.missing_powered: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'powered'-Eigenschaft für das 'pressure_plate_block'-Verhalten.</yellow>"
warning.config.model.generation.missing_parent: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'parent'-Argument im Abschnitt 'generation'.</yellow>"
warning.config.model.generation.invalid_display_position: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet eine ungültige Anzeigeposition '<arg:2>' im Abschnitt 'generation.display'. Erlaubte Anzeigepositionen: [<arg:3>]</yellow>"
warning.config.model.generation.invalid_gui_light: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet eine ungültige GUI-Lichtoption '<arg:2>' im Abschnitt 'generation'. Erlaubte GUI-Lichtoptionen: [<arg:3>]</yellow>"
warning.config.model.generation.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Fehler beim Generieren des Modells für '<arg:1>', da zwei oder mehr Konfigurationen versuchen, verschiedene JSON-Modelle mit demselben Pfad zu generieren: '<arg:2>'.</yellow>"
warning.config.model.generation.texture.invalid: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' hat eine Textur '<arg:2>' mit Pfad '<arg:3>', die illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.model.generation.parent.invalid: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' hat ein 'parent'-Argument '<arg:2>', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.emoji.missing_keywords: "<yellow>Problem in Datei <arg:0> gefunden - Dem Emoji '<arg:1>' fehlt das erforderliche 'keywords'-Argument.</yellow>"
warning.config.emoji.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Dupliziertes Emoji '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.emoji.invalid_image: "<yellow>Problem in Datei <arg:0> gefunden - Das Emoji '<arg:1>' hat ein ungültiges 'image'-Argument '<arg:2>'.</yellow>"
warning.config.advancement.duplicate: "<yellow>Problem in Datei <arg:0> gefunden - Duplizierter Fortschritt '<arg:1>'. Bitte überprüfen Sie, ob dieselbe Konfiguration in anderen Dateien vorhanden ist.</yellow>"
warning.config.loot_table.missing_pools: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, der das erforderliche 'pools'-Argument fehlt.</yellow>"
warning.config.loot_table.invalid_pools_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, 'pools' sollte eine String-/Kartenliste sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.loot_table.invalid_conditions_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, 'conditions' sollte eine Kartenliste sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.loot_table.invalid_functions_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, 'functions' sollte eine Kartenliste sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.loot_table.invalid_entries_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, 'entries' sollte eine Kartenliste sein, aktueller Typ: '<arg:2>'.</yellow>"
warning.config.loot_table.function.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, einer der Funktionen fehlt das erforderliche 'type'-Argument.</yellow>"
warning.config.loot_table.function.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, einer der Funktionen verwendet einen ungültigen Funktionstyp '<arg:2>'.</yellow>"
warning.config.loot_table.function.apply_bonus.missing_enchantment: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, der Funktion 'apply_bonus' fehlt das erforderliche 'enchantment'-Argument.</yellow>"
warning.config.loot_table.function.apply_bonus.missing_formula: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, der Funktion 'apply_bonus' fehlt das erforderliche 'formula'-Argument.</yellow>"
warning.config.loot_table.function.drop_exp.missing_count: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, der Funktion 'drop_exp' fehlt das erforderliche 'count'-Argument.</yellow>"
warning.config.loot_table.function.set_count.missing_count: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, der Funktion 'set_count' fehlt das erforderliche 'count'-Argument.</yellow>"
warning.config.loot_table.entry.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, einem der Einträge fehlt das erforderliche 'type'-Argument.</yellow>"
warning.config.loot_table.entry.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, einem der Einträge verwendet einen ungültigen Eintragstyp '<arg:2>'.</yellow>"
warning.config.loot_table.entry.exp.missing_count: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, dem Eintrag 'exp' fehlt das erforderliche 'count'-Argument.</yellow>"
warning.config.loot_table.entry.item.missing_item: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, dem Eintrag 'item' fehlt das erforderliche 'item'-Argument.</yellow>"
warning.config.loot_table.condition.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, einer der Bedingungen fehlt das erforderliche 'type'-Argument.</yellow>"
warning.config.loot_table.condition.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - '<arg:1>' hat eine falsch konfigurierte Beutetabelle, einer der Bedingungen verwendet einen ungültigen Bedingungstyp '<arg:2>'.</yellow>"
warning.config.host.missing_type: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'type'-Argument für den Host.</yellow>"
warning.config.host.invalid_type: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Host-Typ '<arg:0>' ist ungültig. Bitte lesen Sie https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host.</yellow>"
warning.config.host.external.missing_url: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'url'-Argument für den externen Host.</yellow>"
warning.config.host.alist.missing_api_url: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'api-url'-Argument für den AList-Host.</yellow>"
warning.config.host.alist.missing_username: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'username'-Argument oder Umgebungsvariable 'CE_ALIST_USERNAME' für den AList-Host.</yellow>"
warning.config.host.alist.missing_password: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'password'-Argument oder Umgebungsvariable 'CE_ALIST_PASSWORD' für den AList-Host.</yellow>"
warning.config.host.alist.missing_upload_path: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'upload-path'-Argument für den AList-Host.</yellow>"
warning.config.host.dropbox.missing_app_key: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'app-key'-Argument oder Umgebungsvariable 'CE_DROPBOX_APP_KEY' für den Dropbox-Host.</yellow>"
warning.config.host.dropbox.missing_app_secret: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'app-secret'-Argument oder Umgebungsvariable 'CE_DROPBOX_APP_SECRET' für den Dropbox-Host.</yellow>"
warning.config.host.dropbox.missing_refresh_token: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'refresh-token'-Argument oder Umgebungsvariable 'CE_DROPBOX_REFRESH_TOKEN' für den Dropbox-Host.</yellow>"
warning.config.host.dropbox.missing_upload_path: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'upload-path'-Argument für den Dropbox-Host.</yellow>"
warning.config.host.lobfile.missing_api_key: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'api-key'-Argument für den Lobfile-Host.</yellow>"
warning.config.host.onedrive.missing_client_id: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'client-id'-Argument oder Umgebungsvariable 'CE_ONEDRIVE_CLIENT_ID' für den OneDrive-Host.</yellow>"
warning.config.host.onedrive.missing_client_secret: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'client-secret'-Argument oder Umgebungsvariable 'CE_ONEDRIVE_CLIENT_SECRET' für den OneDrive-Host.</yellow>"
warning.config.host.onedrive.missing_refresh_token: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'refresh-token'-Argument oder Umgebungsvariable 'CE_ONEDRIVE_REFRESH_TOKEN' für den OneDrive-Host.</yellow>"
warning.config.host.onedrive.missing_upload_path: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'upload-path'-Argument für den OneDrive-Host.</yellow>"
warning.config.host.s3.missing_endpoint: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'endpoint'-Argument für den S3-Host.</yellow>"
warning.config.host.s3.missing_bucket: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'bucket'-Argument für den S3-Host.</yellow>"
warning.config.host.s3.missing_access_key: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'access-key-id'-Argument oder Umgebungsvariable 'CE_S3_ACCESS_KEY_ID' für den S3-Host.</yellow>"
warning.config.host.s3.missing_secret: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'access-key-secret'-Argument oder Umgebungsvariable 'CE_S3_ACCESS_KEY_SECRET' für den S3-Host.</yellow>"
warning.config.host.s3.missing_upload_path: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'upload-path'-Argument für den S3-Host.</yellow>"
warning.config.host.self.missing_ip: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'ip'-Argument für den Selbst-Host.</yellow>"
warning.config.host.self.invalid_port: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Ungültiger Port '<arg:0>' für den Selbst-Host.</yellow>"
warning.config.host.self.invalid_url: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Ungültige URL '<arg:0>' für den Selbst-Host.</yellow>"
warning.config.host.gitlab.missing_url: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'gitlab-url'-Argument für den GitLab-Host.</yellow>"
warning.config.host.gitlab.missing_token: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'access-token'-Argument für den GitLab-Host.</yellow>"
warning.config.host.gitlab.missing_project: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'project-id'-Argument für den GitLab-Host.</yellow>"
warning.config.host.proxy.missing_host: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'host'-Argument für den Proxy.</yellow>"
warning.config.host.proxy.missing_port: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'port'-Argument für den Proxy.</yellow>"
warning.config.host.proxy.missing_scheme: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Fehlendes erforderliches 'scheme'-Argument für den Proxy.</yellow>"
warning.config.host.proxy.invalid: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.delivery.hosting' gefunden - Ungültiger Proxy '<arg:0>'.</yellow>"
warning.config.conflict_matcher.missing_type: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'type'-Argument für einen der Handler.</yellow>"
warning.config.conflict_matcher.invalid_type: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Einer der Begriffe verwendet den ungültigen Typ '<arg:0>'.</yellow>"
warning.config.conflict_matcher.exact.missing_path: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'path'-Argument für den 'exact'-Matcher.</yellow>"
warning.config.conflict_matcher.contains.missing_path: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'path'-Argument für den 'contains'-Matcher.</yellow>"
warning.config.conflict_matcher.filename.missing_name: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'path'-Argument für den 'filename'-Matcher.</yellow>"
warning.config.conflict_matcher.pattern.missing_pattern: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'pattern'-Argument für den 'pattern'-Matcher.</yellow>"
warning.config.conflict_matcher.parent_prefix.missing_prefix: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'prefix'-Argument für den 'parent_path_prefix'-Matcher.</yellow>"
warning.config.conflict_matcher.parent_suffix.missing_suffix: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'suffix'-Argument für den 'parent_path_suffix'-Matcher.</yellow>"
warning.config.conflict_matcher.inverted.missing_term: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'term'-Argument für den 'inverted'-Matcher.</yellow>"
warning.config.conflict_matcher.all_of.missing_terms: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'terms'-Argument für den 'all_of'-Matcher.</yellow>"
warning.config.conflict_matcher.any_of.missing_terms: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'terms'-Argument für den 'any_of'-Matcher.</yellow>"
warning.config.conflict_resolution.missing_type: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Fehlendes erforderliches 'type'-Argument für eine der Auflösungen.</yellow>"
warning.config.conflict_resolution.invalid_type: "<yellow>Problem in config.yml im Abschnitt 'resource-pack.duplicated-files-handler' gefunden - Eine der Auflösungen verwendet den ungültigen Typ '<arg:0>'.</yellow>"
warning.config.event.missing_trigger: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'on'-Argument für Ereignisauslöser.</yellow>"
warning.config.event.invalid_trigger: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet einen ungültigen Ereignisauslöser '<arg:2>'.</yellow>"
warning.config.event.condition.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'type'-Argument für die Ereignisbedingung.</yellow>"
warning.config.event.condition.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet ein ungültiges 'type'-Argument '<arg:2>' für die Ereignisbedingung.</yellow>"
warning.config.function.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'type'-Argument für die Funktion.</yellow>"
warning.config.function.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet einen ungültigen Funktionstyp '<arg:2>'.</yellow>"
warning.config.function.command.missing_command: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'command'-Argument für die 'command'-Funktion.</yellow>"
warning.config.function.actionbar.missing_actionbar: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'actionbar'-Argument für die 'actionbar'-Funktion.</yellow>"
warning.config.function.message.missing_message: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'message'-Argument für die 'message'-Funktion.</yellow>"
warning.config.function.open_window.missing_gui_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'gui-type'-Argument für die 'open_window'-Funktion.</yellow>"
warning.config.function.open_window.invalid_gui_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet einen ungültigen GUI-Typ <arg:2> für die 'open_window'-Funktion. Erlaubte Typen: [<arg:3>].</yellow>"
warning.config.function.run.missing_functions: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'functions'-Argument für die 'run'-Funktion.</yellow>"
warning.config.function.place_block.missing_block_state: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'block-state'-Argument für die 'place_block'-Funktion.</yellow>"
warning.config.function.set_food.missing_food: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'food'-Argument für die 'set_food'-Funktion.</yellow>"
warning.config.function.set_saturation.missing_saturation: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'saturation'-Argument für die 'set_saturation'-Funktion.</yellow>"
warning.config.function.play_sound.missing_sound: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'sound'-Argument für die 'play_sound'-Funktion.</yellow>"
warning.config.function.particle.missing_particle: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'particle'-Argument für die 'particle'-Funktion.</yellow>"
warning.config.function.particle.missing_color: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'color'-Argument für die 'particle'-Funktion.</yellow>"
warning.config.function.particle.missing_from: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'from'-Argument für die 'particle'-Funktion.</yellow>"
warning.config.function.particle.missing_to: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'to'-Argument für die 'particle'-Funktion.</yellow>"
warning.config.function.particle.missing_item: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'item'-Argument für die 'particle'-Funktion.</yellow>"
warning.config.function.particle.missing_block_state: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'block-state'-Argument für die 'particle'-Funktion.</yellow>"
warning.config.function.leveler_exp.missing_count: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'count'-Argument für die 'leveler_exp'-Funktion.</yellow>"
warning.config.function.leveler_exp.missing_leveler: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'leveler'-Argument für die 'leveler_exp'-Funktion.</yellow>"
warning.config.function.leveler_exp.missing_plugin: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'plugin'-Argument für die 'leveler_exp'-Funktion.</yellow>"
warning.config.function.remove_potion_effect.missing_potion_effect: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'potion-effect'-Argument für die 'remove_potion_effect'-Funktion.</yellow>"
warning.config.function.potion_effect.missing_potion_effect: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'potion-effect'-Argument für die 'potion_effect'-Funktion.</yellow>"
warning.config.function.set_cooldown.missing_time: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'time'-Argument für die 'set_cooldown'-Funktion.</yellow>"
warning.config.function.set_cooldown.missing_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'id'-Argument für die 'set_cooldown'-Funktion.</yellow>"
warning.config.function.remove_cooldown.missing_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'id'-Argument für die 'remove_cooldown'-Funktion.</yellow>"
warning.config.selector.missing_type: "<yellow>Problem in Datei <arg:0> gefunden - Der Konfiguration '<arg:1>' fehlt das erforderliche 'type'-Argument für den Selektor.</yellow>"
warning.config.selector.invalid_type: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet einen ungültigen Selektortyp '<arg:2>'.</yellow>"
warning.config.selector.invalid_target: "<yellow>Problem in Datei <arg:0> gefunden - Die Konfiguration '<arg:1>' verwendet ein ungültiges Selektorziel '<arg:2>'.</yellow>"
warning.config.resource_pack.item_model.conflict.vanilla: "<yellow>Fehler beim Generieren des Gegenstandsmodells für '<arg:0>' da dieses Gegenstandsmodell von einem Vanilla-Gegenstand belegt wurde.</yellow>"
warning.config.resource_pack.item_model.already_exist: "<yellow>Fehler beim Generieren des Gegenstandsmodells für '<arg:0>' da die Datei '<arg:1>' bereits existiert.</yellow>"
warning.config.resource_pack.model.generation.already_exist: "<yellow>Fehler beim Generieren des Modells, da die Modelldatei '<arg:0>' bereits existiert.</yellow>"
warning.config.resource_pack.generation.missing_font_texture: "<yellow>Schriftart '<arg:0>' fehlt die erforderliche Textur: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_model_texture: "<yellow>Modell '<arg:0>' fehlt Textur '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_item_model: "<yellow>Gegenstand '<arg:0>' fehlt Modelldatei: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_block_model: "<yellow>Block '<arg:0>' fehlt Modelldatei: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_parent_model: "<yellow>Modell '<arg:0>' kann das Elternmodell nicht finden: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json-Datei '<arg:0>' ist fehlerhaft formatiert.</yellow>"
warning.config.resource_pack.invalid_overlay_format: "<yellow>Problem in config.yml gefunden - Ungültiges Overlay-Format '<arg:0>' im Abschnitt 'resource-pack'. Unterstützte Overlays: [<arg:1>]</yellow>"

View File

@@ -186,8 +186,10 @@ warning.config.item.model.condition.missing_property: "<yellow>Issue found in fi
warning.config.item.model.condition.invalid_property: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid property '<arg:2>' for model 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.missing_on_true: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'on-true' argument for model 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.missing_on_false: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'on-false' argument for model 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.keybind.missing: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'keybind' argument for property 'minecraft:keybind_down'.</yellow>"
warning.config.item.model.condition.keybind.missing_keybind: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'keybind' argument for property 'minecraft:keybind_down'.</yellow>"
warning.config.item.model.condition.has_component.missing_component: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'component' argument for property 'minecraft:has_component'.</yellow>"
warning.config.item.model.condition.component.missing_predicate: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'predicate' argument for property 'minecraft:component'.</yellow>"
warning.config.item.model.condition.component.missing_value: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'value' argument for property 'minecraft:component'.</yellow>"
warning.config.item.model.composite.missing_models: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'models' argument for 'minecraft:composite' model.</yellow>"
warning.config.item.model.range_dispatch.missing_property: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'property' argument for model 'minecraft:range_dispatch'.</yellow>"
warning.config.item.model.range_dispatch.invalid_property: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid property '<arg:2>' for model 'minecraft:range_dispatch'.</yellow>"
@@ -202,6 +204,7 @@ warning.config.item.model.select.case.missing_when: "<yellow>Issue found in file
warning.config.item.model.select.case.missing_model: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'model' argument for one of the cases in model 'minecraft:select'.</yellow>"
warning.config.item.model.select.block_state.missing_property: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'block-state-property' argument for property 'minecraft:block_state'.</yellow>"
warning.config.item.model.select.local_time.missing_pattern: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'pattern' argument for property 'minecraft:local_time'.</yellow>"
warning.config.item.model.select.component.missing_component: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'component' argument for property 'minecraft:component'.</yellow>"
warning.config.item.model.special.missing_type: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'type' argument for model 'minecraft:special'.</yellow>"
warning.config.item.model.special.missing_path: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'path' argument for model 'minecraft:special'.</yellow>"
warning.config.item.model.special.invalid_path: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' has an invalid 'path' argument '<arg:2>' for model 'minecraft:special' which contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
@@ -385,4 +388,5 @@ warning.config.resource_pack.generation.missing_model_texture: "<yellow>Model '<
warning.config.resource_pack.generation.missing_item_model: "<yellow>Item '<arg:0>' is missing model file: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_block_model: "<yellow>Block '<arg:0>' is missing model file: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_parent_model: "<yellow>Model '<arg:0>' cannot find parent model: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json file '<arg:0>' is malformatted.</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json file '<arg:0>' is malformatted.</yellow>"
warning.config.resource_pack.invalid_overlay_format: "<yellow>Issue found in config.yml at 'resource-pack.overlay-format' - Invalid overlay format '<arg:0>'. Overlay format must contain the placeholder '{version}'.</yellow>"

View File

@@ -140,7 +140,7 @@ warning.config.item.model.condition.missing_property: "<yellow>Problema encontra
warning.config.item.model.condition.invalid_property: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' está usando una propiedad inválida '<arg:2>' para el modelo 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.missing_on_true: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'on-true' para el modelo 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.missing_on_false: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'on-false' para el modelo 'minecraft:condition'.</yellow>"
warning.config.item.model.condition.keybind.missing: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'keybind' para la propiedad 'minecraft:keybind_down'.</yellow>"
warning.config.item.model.condition.keybind.missing_keybind: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'keybind' para la propiedad 'minecraft:keybind_down'.</yellow>"
warning.config.item.model.condition.has_component.missing_component: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'component' para la propiedad 'minecraft:has_component'.</yellow>"
warning.config.item.model.composite.missing_models: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'models' para el modelo 'minecraft:composite'.</yellow>"
warning.config.item.model.range_dispatch.missing_property: "<yellow>Problema encontrado en el archivo <arg:0> - El objeto '<arg:1>' carece del argumento requerido 'property' para el modelo 'minecraft:range_dispatch'.</yellow>"

View File

@@ -139,7 +139,7 @@ warning.config.item.model.condition.missing_property: "<yellow><arg:0> dosyasın
warning.config.item.model.condition.invalid_property: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:condition' modeli için geçersiz bir özellik '<arg:2>' kullanıyor.</yellow>"
warning.config.item.model.condition.missing_on_true: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:condition' modeli için gerekli 'on-true' argümanı eksik.</yellow>"
warning.config.item.model.condition.missing_on_false: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:condition' modeli için gerekli 'on-false' argümanı eksik.</yellow>"
warning.config.item.model.condition.keybind.missing: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:keybind_down' özelliği için gerekli 'keybind' argümanı eksik.</yellow>"
warning.config.item.model.condition.keybind.missing_keybind: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:keybind_down' özelliği için gerekli 'keybind' argümanı eksik.</yellow>"
warning.config.item.model.condition.has_component.missing_component: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:has_component' özelliği için gerekli 'component' argümanı eksik.</yellow>"
warning.config.item.model.composite.missing_models: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:composite' modeli için gerekli 'models' argümanı eksik.</yellow>"
warning.config.item.model.range_dispatch.missing_property: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:range_dispatch' modeli için gerekli 'property' argümanı eksik.</yellow>"

View File

@@ -186,8 +186,10 @@ warning.config.item.model.condition.missing_property: "<yellow>在文件 <arg:0>
warning.config.item.model.condition.invalid_property: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:condition' 模型使用了无效属性 '<arg:2>'</yellow>"
warning.config.item.model.condition.missing_on_true: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:condition' 模型缺少必需的 'on-true' 参数</yellow>"
warning.config.item.model.condition.missing_on_false: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:condition' 模型缺少必需的 'on-false' 参数</yellow>"
warning.config.item.model.condition.keybind.missing: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:keybind_down' 属性缺少必需的 'keybind' 参数</yellow>"
warning.config.item.model.condition.keybind.missing_keybind: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:keybind_down' 属性缺少必需的 'keybind' 参数</yellow>"
warning.config.item.model.condition.has_component.missing_component: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:has_component' 属性缺少必需的 'component' 参数</yellow>"
warning.config.item.model.condition.component.missing_predicate: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:component' 属性缺少必需的 'predicate' 参数.</yellow>"
warning.config.item.model.condition.component.missing_value: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:component' 属性缺少必需的 'value' 参数.</yellow>"
warning.config.item.model.composite.missing_models: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:composite' 模型缺少必需的 'models' 参数</yellow>"
warning.config.item.model.range_dispatch.missing_property: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:range_dispatch' 模型缺少必需的 'property' 参数</yellow>"
warning.config.item.model.range_dispatch.invalid_property: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:range_dispatch' 模型使用了无效属性 '<arg:2>'</yellow>"
@@ -202,6 +204,7 @@ warning.config.item.model.select.case.missing_when: "<yellow>在文件 <arg:0>
warning.config.item.model.select.case.missing_model: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:select' 模型的某个 case 缺少必需的 'model' 参数</yellow>"
warning.config.item.model.select.block_state.missing_property: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:block_state' 属性缺少必需的 'block-state-property' 参数</yellow>"
warning.config.item.model.select.local_time.missing_pattern: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:local_time' 属性缺少必需的 'pattern' 参数</yellow>"
warning.config.item.model.select.component.missing_component: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:component' 属性缺少必需的 'component' 参数</yellow>"
warning.config.item.model.special.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:special' 模型缺少必需的 'type' 参数</yellow>"
warning.config.item.model.special.missing_path: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:special' 模型缺少必需的模型 'path' 参数</yellow>"
warning.config.item.model.special.invalid_path: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:special' 模型路径 '<arg:2>' 包含非法字符 请参考 https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
@@ -385,4 +388,5 @@ warning.config.resource_pack.generation.missing_model_texture: "<yellow>模型'<
warning.config.resource_pack.generation.missing_item_model: "<yellow>物品'<arg:0>'缺少模型文件: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_block_model: "<yellow>方块'<arg:0>'缺少模型文件: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.missing_parent_model: "<yellow>模型'<arg:0>'找不到父级模型文件: '<arg:1>'</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json文件 '<arg:0>' 格式错误.</yellow>"
warning.config.resource_pack.generation.malformatted_json: "<yellow>Json文件 '<arg:0>' 格式错误.</yellow>"
warning.config.resource_pack.invalid_overlay_format: "<yellow>在 config.yml 的 'resource-pack.overlay-format' 处发现问题 - 无效的overlay格式 '<arg:0>'. Overlay格式必须包含占位符 '{version}'.</yellow>"

View File

@@ -263,15 +263,13 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
public class ItemParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"items", "item"};
private static final float VERSION_1_21_2 = 21.2f;
private static final float VERSION_1_21_4 = 21.4f;
private boolean isModernFormatRequired() {
return Config.packMaxVersion() >= VERSION_1_21_4;
return Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_4);
}
private boolean needsLegacyCompatibility() {
return Config.packMinVersion() < VERSION_1_21_4;
return Config.packMinVersion().isBelow(MinecraftVersions.V1_21_4);
}
@Override
@@ -433,7 +431,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
ResourceConfigUtils.getAsBoolean(section.getOrDefault("hand-animation-on-swap", true), "hand-animation-on-swap")
));
}
if (Config.packMaxVersion() >= VERSION_1_21_2 && needsLegacyCompatibility() && legacyOverridesModels != null && !legacyOverridesModels.isEmpty()) {
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2) && needsLegacyCompatibility() && legacyOverridesModels != null && !legacyOverridesModels.isEmpty()) {
TreeSet<LegacyOverridesModel> lom = AbstractItemManager.this.modernItemModels1_21_2.computeIfAbsent(itemModelKey, k -> new TreeSet<>());
lom.addAll(legacyOverridesModels);
}

View File

@@ -1,7 +1,6 @@
package net.momirealms.craftengine.core.item.modifier;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;

View File

@@ -17,11 +17,15 @@ import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
import net.momirealms.craftengine.core.pack.host.ResourcePackHosts;
import net.momirealms.craftengine.core.pack.host.impl.NoneHost;
import net.momirealms.craftengine.core.pack.misc.EquipmentGeneration;
import net.momirealms.craftengine.core.pack.model.ItemModel;
import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel;
import net.momirealms.craftengine.core.pack.model.ModernItemModel;
import net.momirealms.craftengine.core.pack.model.RangeDispatchItemModel;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.generation.ModelGenerator;
import net.momirealms.craftengine.core.pack.model.rangedisptach.CustomModelDataRangeDispatchProperty;
import net.momirealms.craftengine.core.pack.obfuscation.ObfA;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
@@ -54,11 +58,12 @@ import java.util.function.Predicate;
import static net.momirealms.craftengine.core.util.MiscUtils.castToMap;
@SuppressWarnings("DuplicatedCode")
public abstract class AbstractPackManager implements PackManager {
public static final Map<Key, JsonObject> PRESET_MODERN_MODELS_ITEM = new HashMap<>();
public static final Map<Key, JsonObject> PRESET_LEGACY_MODELS_ITEM = new HashMap<>();
public static final Map<Key, JsonObject> PRESET_MODELS_BLOCK = new HashMap<>();
public static final Map<Key, JsonObject> PRESET_ITEMS = new HashMap<>();
public static final Map<Key, ModernItemModel> PRESET_ITEMS = new HashMap<>();
public static final Set<Key> VANILLA_TEXTURES = new HashSet<>();
public static final Set<Key> VANILLA_MODELS = new HashSet<>();
private static final byte[] EMPTY_IMAGE;
@@ -103,7 +108,7 @@ public abstract class AbstractPackManager implements PackManager {
loadInternalData("internal/models/item/legacy/_all.json", PRESET_LEGACY_MODELS_ITEM::put);
loadInternalData("internal/models/item/_all.json", PRESET_MODERN_MODELS_ITEM::put);
loadInternalData("internal/models/block/_all.json", PRESET_MODELS_BLOCK::put);
loadInternalData("internal/items/_all.json", PRESET_ITEMS::put);
loadModernItemModel("internal/items/_all.json", PRESET_ITEMS::put);
loadInternalList("textures", "block/", VANILLA_TEXTURES::add);
loadInternalList("textures", "item/", VANILLA_TEXTURES::add);
@@ -122,6 +127,21 @@ public abstract class AbstractPackManager implements PackManager {
}
}
private void loadModernItemModel(String path, BiConsumer<Key, ModernItemModel> callback) {
try (InputStream inputStream = this.plugin.resourceStream(path)) {
if (inputStream != null) {
JsonObject allModelsItems = JsonParser.parseReader(new InputStreamReader(inputStream)).getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : allModelsItems.entrySet()) {
if (entry.getValue() instanceof JsonObject modelJson) {
callback.accept(Key.of(entry.getKey()), ModernItemModel.fromJson(modelJson));
}
}
}
} catch (IOException e) {
this.plugin.logger().warn("Failed to load " + path, e);
}
}
private void loadInternalData(String path, BiConsumer<Key, JsonObject> callback) {
try (InputStream inputStream = this.plugin.resourceStream(path)) {
if (inputStream != null) {
@@ -311,7 +331,7 @@ public abstract class AbstractPackManager implements PackManager {
// internal
plugin.saveResource("resources/remove_shulker_head/resourcepack/pack.mcmeta");
plugin.saveResource("resources/remove_shulker_head/resourcepack/assets/minecraft/shaders/core/rendertype_entity_solid.fsh");
plugin.saveResource("resources/remove_shulker_head/resourcepack/1_20_5_assets/minecraft/shaders/core/rendertype_entity_solid.fsh");
plugin.saveResource("resources/remove_shulker_head/resourcepack/1_20_5_remove_shulker_head_overlay/minecraft/shaders/core/rendertype_entity_solid.fsh");
plugin.saveResource("resources/remove_shulker_head/resourcepack/assets/minecraft/textures/entity/shulker/shulker_white.png");
plugin.saveResource("resources/remove_shulker_head/pack.yml");
// internal
@@ -602,19 +622,21 @@ public abstract class AbstractPackManager implements PackManager {
}
}
HashSet<Revision> revisions = new HashSet<>();
this.generateFonts(generatedPackPath);
this.generateItemModels(generatedPackPath, this.plugin.itemManager());
this.generateItemModels(generatedPackPath, this.plugin.blockManager());
this.generateBlockOverrides(generatedPackPath);
this.generateLegacyItemOverrides(generatedPackPath);
this.generateModernItemOverrides(generatedPackPath);
this.generateModernItemOverrides(generatedPackPath, revisions::add);
this.generateModernItemModels1_21_2(generatedPackPath);
this.generateModernItemModels1_21_4(generatedPackPath);
this.generateModernItemModels1_21_4(generatedPackPath, revisions::add);
this.generateOverrideSounds(generatedPackPath);
this.generateCustomSounds(generatedPackPath);
this.generateClientLang(generatedPackPath);
this.generateEquipments(generatedPackPath);
this.generateParticle(generatedPackPath);
this.generatePackMetadata(generatedPackPath.resolve("pack.mcmeta"), revisions);
if (Config.excludeShaders()) {
this.removeAllShaders(generatedPackPath);
}
@@ -634,6 +656,57 @@ public abstract class AbstractPackManager implements PackManager {
}
}
private void generatePackMetadata(Path path, Set<Revision> revisions) throws IOException {
JsonObject rawMeta;
boolean changed = false;
if (!Files.exists(path)) {
rawMeta = new JsonObject();
changed = true;
} else {
rawMeta = GsonHelper.readJsonFile(path).getAsJsonObject();
}
if (!rawMeta.has("pack")) {
JsonObject pack = new JsonObject();
rawMeta.add("pack", pack);
pack.addProperty("pack_format", Config.packMinVersion().packFormat());
JsonObject supportedFormats = new JsonObject();
supportedFormats.addProperty("min_inclusive", Config.packMinVersion().packFormat());
supportedFormats.addProperty("max_inclusive", Config.packMaxVersion().packFormat());
pack.add("supported_formats", supportedFormats);
changed = true;
}
if (revisions.isEmpty()) {
if (changed) {
GsonHelper.writeJsonFile(rawMeta, path);
}
return;
}
JsonObject overlays;
if (rawMeta.has("overlays")) {
overlays = rawMeta.get("overlays").getAsJsonObject();
} else {
overlays = new JsonObject();
rawMeta.add("overlays", overlays);
}
JsonArray entries;
if (overlays.has("entries")) {
entries = overlays.get("entries").getAsJsonArray();
} else {
entries = new JsonArray();
overlays.add("entries", entries);
}
for (Revision revision : revisions) {
JsonObject entry = new JsonObject();
JsonObject formats = new JsonObject();
entry.add("formats", formats);
formats.addProperty("min_inclusive", revision.minPackVersion());
formats.addProperty("max_inclusive", revision.maxPackVersion());
entry.addProperty("directory", Config.createOverlayFolderName(revision.versionString()));
entries.add(entry);
}
GsonHelper.writeJsonFile(rawMeta, path);
}
private void removeAllShaders(Path path) {
List<Path> rootPaths;
try {
@@ -945,7 +1018,7 @@ public abstract class AbstractPackManager implements PackManager {
private void generateParticle(Path generatedPackPath) {
if (!Config.removeTintedLeavesParticle()) return;
if (Config.packMaxVersion() < 21.49f) return;
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_5)) return;
JsonObject particleJson = new JsonObject();
JsonArray textures = new JsonArray();
textures.add("empty");
@@ -979,7 +1052,7 @@ public abstract class AbstractPackManager implements PackManager {
private void generateEquipments(Path generatedPackPath) {
for (EquipmentGeneration generator : this.plugin.itemManager().equipmentsToGenerate()) {
EquipmentData equipmentData = generator.modernData();
if (equipmentData != null && Config.packMaxVersion() >= 21.4f) {
if (equipmentData != null && Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) {
Path equipmentPath = generatedPackPath
.resolve("assets")
.resolve(equipmentData.assetId().namespace())
@@ -1012,7 +1085,7 @@ public abstract class AbstractPackManager implements PackManager {
this.plugin.logger().severe("Error writing equipment file", e);
}
}
if (equipmentData != null && Config.packMaxVersion() >= 21.2f && Config.packMinVersion() < 21.4f) {
if (equipmentData != null && Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2) && Config.packMinVersion().isBelow(MinecraftVersions.V1_21_4)) {
Path equipmentPath = generatedPackPath
.resolve("assets")
.resolve(equipmentData.assetId().namespace())
@@ -1257,8 +1330,8 @@ public abstract class AbstractPackManager implements PackManager {
}
private void generateModernItemModels1_21_2(Path generatedPackPath) {
if (Config.packMaxVersion() < 21.19f) return;
if (Config.packMinVersion() > 21.39f) return;
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_2)) return;
if (Config.packMinVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) return;
// 此段代码生成1.21.2专用的item model文件情况非常复杂
for (Map.Entry<Key, TreeSet<LegacyOverridesModel>> entry : this.plugin.itemManager().modernItemModels1_21_2().entrySet()) {
@@ -1323,8 +1396,8 @@ public abstract class AbstractPackManager implements PackManager {
}
}
private void generateModernItemModels1_21_4(Path generatedPackPath) {
if (Config.packMaxVersion() < 21.39f) return;
private void generateModernItemModels1_21_4(Path generatedPackPath, Consumer<Revision> callback) {
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_4)) return;
for (Map.Entry<Key, ModernItemModel> entry : this.plugin.itemManager().modernItemModels1_21_4().entrySet()) {
Key key = entry.getKey();
Path itemPath = generatedPackPath
@@ -1347,25 +1420,43 @@ public abstract class AbstractPackManager implements PackManager {
this.plugin.logger().severe("Error creating " + itemPath.toAbsolutePath(), e);
continue;
}
JsonObject model = new JsonObject();
ModernItemModel modernItemModel = entry.getValue();
model.add("model", modernItemModel.itemModel().get());
if (!modernItemModel.handAnimationOnSwap()) {
model.addProperty("hand_animation_on_swap", false);
}
if (modernItemModel.oversizedInGui()) {
model.addProperty("oversized_in_gui", true);
}
try (BufferedWriter writer = Files.newBufferedWriter(itemPath)) {
GsonHelper.get().toJson(model, writer);
GsonHelper.get().toJson(modernItemModel.toJson(Config.packMinVersion()), writer);
} catch (IOException e) {
this.plugin.logger().warn("Failed to save item model for " + key, e);
}
List<Revision> revisions = modernItemModel.revisions();
if (!revisions.isEmpty()) {
for (Revision revision : revisions) {
if (revision.matches(Config.packMinVersion(), Config.packMaxVersion())) {
Path overlayItemPath = generatedPackPath
.resolve(Config.createOverlayFolderName(revision.versionString()))
.resolve("assets")
.resolve(key.namespace())
.resolve("items")
.resolve(key.value() + ".json");
try {
Files.createDirectories(overlayItemPath.getParent());
} catch (IOException e) {
this.plugin.logger().severe("Error creating " + overlayItemPath.toAbsolutePath(), e);
continue;
}
try (BufferedWriter writer = Files.newBufferedWriter(overlayItemPath)) {
GsonHelper.get().toJson(modernItemModel.toJson(revision.minVersion()), writer);
callback.accept(revision);
} catch (IOException e) {
this.plugin.logger().warn("Failed to save item model for " + key, e);
}
}
}
}
}
}
private void generateModernItemOverrides(Path generatedPackPath) {
if (Config.packMaxVersion() < 21.39f) return;
private void generateModernItemOverrides(Path generatedPackPath, Consumer<Revision> callback) {
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_4)) return;
for (Map.Entry<Key, TreeMap<Integer, ModernItemModel>> entry : this.plugin.itemManager().modernItemOverrides().entrySet()) {
Key vanillaItemModel = entry.getKey();
Path overridedItemPath = generatedPackPath
@@ -1374,10 +1465,10 @@ public abstract class AbstractPackManager implements PackManager {
.resolve("items")
.resolve(vanillaItemModel.value() + ".json");
JsonObject originalItemModel;
ModernItemModel originalItemModel;
if (Files.exists(overridedItemPath)) {
try {
originalItemModel = GsonHelper.readJsonFile(overridedItemPath).getAsJsonObject();
originalItemModel = ModernItemModel.fromJson(GsonHelper.readJsonFile(overridedItemPath).getAsJsonObject());
} catch (IOException e) {
this.plugin.logger().warn("Failed to load existing item model (modern)", e);
continue;
@@ -1390,24 +1481,13 @@ public abstract class AbstractPackManager implements PackManager {
}
}
boolean handAnimationOnSwap = Optional.ofNullable(originalItemModel.get("hand_animation_on_swap")).map(JsonElement::getAsBoolean).orElse(true);
boolean oversizedInGui = Optional.ofNullable(originalItemModel.get("oversized_in_gui")).map(JsonElement::getAsBoolean).orElse(false);
JsonObject fallbackModel = originalItemModel.get("model").getAsJsonObject();
JsonObject newJson = new JsonObject();
JsonObject model = new JsonObject();
newJson.add("model", model);
model.addProperty("type", "minecraft:range_dispatch");
model.addProperty("property", "minecraft:custom_model_data");
// 将原有的json读成fallback
model.add("fallback", fallbackModel);
JsonArray entries = new JsonArray();
model.add("entries", entries);
boolean handAnimationOnSwap = originalItemModel.handAnimationOnSwap();
boolean oversizedInGui = originalItemModel.oversizedInGui();
Map<Float, ItemModel> entries = new HashMap<>();
for (Map.Entry<Integer, ModernItemModel> modelWithDataEntry : entry.getValue().entrySet()) {
JsonObject entryObject = new JsonObject();
ModernItemModel modernItemModel = modelWithDataEntry.getValue();
entryObject.addProperty("threshold", modelWithDataEntry.getKey());
entryObject.add("model", modernItemModel.itemModel().get());
entries.add(entryObject);
entries.put(modelWithDataEntry.getKey().floatValue(), modernItemModel.itemModel());
if (modernItemModel.handAnimationOnSwap()) {
handAnimationOnSwap = true;
}
@@ -1415,28 +1495,58 @@ public abstract class AbstractPackManager implements PackManager {
oversizedInGui = true;
}
}
if (!handAnimationOnSwap) {
newJson.addProperty("hand_animation_on_swap", false);
}
if (oversizedInGui) {
newJson.addProperty("oversized_in_gui", true);
}
RangeDispatchItemModel rangeDispatch = new RangeDispatchItemModel(
new CustomModelDataRangeDispatchProperty(0),
1f,
originalItemModel.itemModel(),
entries
);
ModernItemModel newItemModel = new ModernItemModel(rangeDispatch, handAnimationOnSwap, oversizedInGui);
try {
Files.createDirectories(overridedItemPath.getParent());
} catch (IOException e) {
this.plugin.logger().severe("Error creating " + overridedItemPath.toAbsolutePath(), e);
continue;
}
try (BufferedWriter writer = Files.newBufferedWriter(overridedItemPath)) {
GsonHelper.get().toJson(newJson, writer);
GsonHelper.get().toJson(newItemModel.toJson(Config.packMinVersion()), writer);
} catch (IOException e) {
this.plugin.logger().warn("Failed to save item model for " + vanillaItemModel, e);
}
List<Revision> revisions = newItemModel.revisions();
if (!revisions.isEmpty()) {
for (Revision revision : revisions) {
if (revision.matches(Config.packMinVersion(), Config.packMaxVersion())) {
Path overlayItemPath = generatedPackPath
.resolve(Config.createOverlayFolderName(revision.versionString()))
.resolve("assets")
.resolve(vanillaItemModel.namespace())
.resolve("items")
.resolve(vanillaItemModel.value() + ".json");
try {
Files.createDirectories(overlayItemPath.getParent());
} catch (IOException e) {
this.plugin.logger().severe("Error creating " + overlayItemPath.toAbsolutePath(), e);
continue;
}
try (BufferedWriter writer = Files.newBufferedWriter(overlayItemPath)) {
GsonHelper.get().toJson(newItemModel.toJson(revision.minVersion()), writer);
callback.accept(revision);
} catch (IOException e) {
this.plugin.logger().warn("Failed to save item model for " + vanillaItemModel, e);
}
}
}
}
}
}
private void generateLegacyItemOverrides(Path generatedPackPath) {
if (Config.packMinVersion() > 21.39f) return;
if (Config.packMinVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) return;
for (Map.Entry<Key, TreeSet<LegacyOverridesModel>> entry : this.plugin.itemManager().legacyItemOverrides().entrySet()) {
Key vanillaLegacyModel = entry.getKey();
Path overridedItemPath = generatedPackPath

View File

@@ -1,13 +1,16 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.ResourceLocation;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.tint.Tint;
import net.momirealms.craftengine.core.pack.model.tint.Tints;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
@@ -18,6 +21,7 @@ import java.util.Map;
public class BaseItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String path;
private final List<Tint> tints;
private final ModelGeneration modelGeneration;
@@ -29,21 +33,21 @@ public class BaseItemModel implements ItemModel {
}
public List<Tint> tints() {
return tints;
return this.tints;
}
public String path() {
return path;
return this.path;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("model", path);
if (!tints.isEmpty()) {
json.addProperty("model", this.path);
if (!this.tints.isEmpty()) {
JsonArray array = new JsonArray();
for (Tint tint : tints) {
for (Tint tint : this.tints) {
array.add(tint.get());
}
json.add("tints", array);
@@ -65,6 +69,11 @@ public class BaseItemModel implements ItemModel {
}
}
@Override
public List<Revision> revisions() {
return List.of();
}
public static class Factory implements ItemModelFactory {
@SuppressWarnings("unchecked")
@@ -91,4 +100,26 @@ public class BaseItemModel implements ItemModel {
}
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
String model = json.get("model").getAsString();
if (json.has("tints")) {
JsonArray array = json.getAsJsonArray("tints");
List<Tint> tints = new ArrayList<>(array.size());
for (JsonElement element : array) {
if (element instanceof JsonObject jo) {
tints.add(Tints.fromJson(jo));
} else {
throw new IllegalArgumentException("tint is expected to be a json object");
}
}
return new BaseItemModel(model, tints, null);
} else {
return new BaseItemModel(model, List.of(), null);
}
}
}
}

View File

@@ -0,0 +1,52 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import java.util.List;
import java.util.Map;
public class BundleSelectedItemModel implements ItemModel {
public static final BundleSelectedItemModel INSTANCE = new BundleSelectedItemModel();
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
@Override
public Key type() {
return ItemModels.BUNDLE_SELECTED_ITEM;
}
@Override
public List<ModelGeneration> modelsToGenerate() {
return List.of();
}
@Override
public List<Revision> revisions() {
return List.of();
}
@Override
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
return json;
}
public static class Factory implements ItemModelFactory {
@Override
public ItemModel create(Map<String, Object> arguments) {
return INSTANCE;
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -1,10 +1,13 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import java.util.ArrayList;
@@ -13,6 +16,7 @@ import java.util.Map;
public class CompositeItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final List<ItemModel> models;
public CompositeItemModel(List<ItemModel> models) {
@@ -20,16 +24,16 @@ public class CompositeItemModel implements ItemModel {
}
public List<ItemModel> models() {
return models;
return this.models;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
JsonArray array = new JsonArray();
for (ItemModel model : models) {
array.add(model.get());
for (ItemModel model : this.models) {
array.add(model.apply(version));
}
json.add("models", array);
return json;
@@ -40,6 +44,15 @@ public class CompositeItemModel implements ItemModel {
return ItemModels.COMPOSITE;
}
@Override
public List<Revision> revisions() {
List<Revision> versions = new ArrayList<>();
for (ItemModel model : this.models) {
versions.addAll(model.revisions());
}
return versions;
}
@Override
public List<ModelGeneration> modelsToGenerate() {
List<ModelGeneration> models = new ArrayList<>(4);
@@ -72,4 +85,24 @@ public class CompositeItemModel implements ItemModel {
}
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
JsonArray models = json.getAsJsonArray("models");
if (models == null) {
throw new IllegalArgumentException("models is expected to be a JsonArray");
}
List<ItemModel> modelList = new ArrayList<>();
for (JsonElement model : models) {
if (model instanceof JsonObject jo) {
modelList.add(ItemModels.fromJson(jo));
} else {
throw new IllegalArgumentException("model is expected to be a JsonObject");
}
}
return new CompositeItemModel(modelList);
}
}
}

View File

@@ -4,8 +4,10 @@ import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.condition.ConditionProperties;
import net.momirealms.craftengine.core.pack.model.condition.ConditionProperty;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import java.util.ArrayList;
@@ -14,6 +16,7 @@ import java.util.Map;
public class ConditionItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final ConditionProperty property;
private final ItemModel onTrue;
private final ItemModel onFalse;
@@ -25,15 +28,15 @@ public class ConditionItemModel implements ItemModel {
}
public ConditionProperty property() {
return property;
return this.property;
}
public ItemModel onTrue() {
return onTrue;
return this.onTrue;
}
public ItemModel onFalse() {
return onFalse;
return this.onFalse;
}
@Override
@@ -41,21 +44,35 @@ public class ConditionItemModel implements ItemModel {
return ItemModels.CONDITION;
}
@Override
public List<Revision> revisions() {
List<Revision> onTrueVersions = this.onTrue.revisions();
List<Revision> onFalseVersions = this.onFalse.revisions();
if (onTrueVersions.isEmpty() && onFalseVersions.isEmpty()) return List.of();
List<Revision> versions = new ArrayList<>(onTrueVersions.size() + onFalseVersions.size());
versions.addAll(onTrueVersions);
versions.addAll(onFalseVersions);
return versions;
}
@Override
public List<ModelGeneration> modelsToGenerate() {
List<ModelGeneration> models = new ArrayList<>(4);
models.addAll(onTrue.modelsToGenerate());
models.addAll(onFalse.modelsToGenerate());
List<ModelGeneration> onTrueModels = this.onTrue.modelsToGenerate();
List<ModelGeneration> onFalseModels = this.onFalse.modelsToGenerate();
if (onTrueModels.isEmpty() && onFalseModels.isEmpty()) return List.of();
List<ModelGeneration> models = new ArrayList<>(onTrueModels.size() + onFalseModels.size());
models.addAll(onTrueModels);
models.addAll(onFalseModels);
return models;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.add("on_true", onTrue.get());
json.add("on_false", onFalse.get());
property.accept(json);
json.add("on_true", this.onTrue.apply(version));
json.add("on_false", this.onFalse.apply(version));
this.property.accept(json);
return json;
}
@@ -79,4 +96,15 @@ public class ConditionItemModel implements ItemModel {
return new ConditionItemModel(property, onTrue, onFalse);
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
ConditionProperty property = ConditionProperties.fromJson(json);
ItemModel onTrue = ItemModels.fromJson(json.getAsJsonObject("on_true"));
ItemModel onFalse = ItemModels.fromJson(json.getAsJsonObject("on_false"));
return new ConditionItemModel(property, onTrue, onFalse);
}
}
}

View File

@@ -2,17 +2,20 @@ package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import java.util.List;
import java.util.Map;
public class EmptyItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private static final EmptyItemModel INSTANCE = new EmptyItemModel();
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
return json;
@@ -28,11 +31,22 @@ public class EmptyItemModel implements ItemModel {
return List.of();
}
public static class Factory implements ItemModelFactory {
@Override
public List<Revision> revisions() {
return List.of();
}
public static class Factory implements ItemModelFactory {
@Override
public ItemModel create(Map<String, Object> arguments) {
return INSTANCE;
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -2,14 +2,18 @@ package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import java.util.List;
import java.util.function.Supplier;
import java.util.function.Function;
public interface ItemModel extends Supplier<JsonObject> {
public interface ItemModel extends Function<MinecraftVersion, JsonObject> {
Key type();
List<ModelGeneration> modelsToGenerate();
List<Revision> revisions();
}

View File

@@ -0,0 +1,8 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonObject;
public interface ItemModelReader {
ItemModel read(JsonObject json);
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -18,23 +19,39 @@ public class ItemModels {
public static final Key RANGE_DISPATCH = Key.of("minecraft:range_dispatch");
public static final Key SELECT = Key.of("minecraft:select");
public static final Key SPECIAL = Key.of("minecraft:special");
public static final Key BUNDLE_SELECTED_ITEM = Key.of("minecraft:bundle/selected_item");
static {
register(EMPTY, EmptyItemModel.FACTORY);
register(COMPOSITE, CompositeItemModel.FACTORY);
register(MODEL, BaseItemModel.FACTORY);
register(CONDITION, ConditionItemModel.FACTORY);
register(SPECIAL, SpecialItemModel.FACTORY);
register(RANGE_DISPATCH, RangeDispatchItemModel.FACTORY);
register(SELECT, SelectItemModel.FACTORY);
registerFactory(EMPTY, EmptyItemModel.FACTORY);
registerReader(EMPTY, EmptyItemModel.READER);
registerFactory(COMPOSITE, CompositeItemModel.FACTORY);
registerReader(COMPOSITE, CompositeItemModel.READER);
registerFactory(MODEL, BaseItemModel.FACTORY);
registerReader(MODEL, BaseItemModel.READER);
registerFactory(CONDITION, ConditionItemModel.FACTORY);
registerReader(CONDITION, ConditionItemModel.READER);
registerFactory(SPECIAL, SpecialItemModel.FACTORY);
registerReader(SPECIAL, SpecialItemModel.READER);
registerFactory(RANGE_DISPATCH, RangeDispatchItemModel.FACTORY);
registerReader(RANGE_DISPATCH, RangeDispatchItemModel.READER);
registerFactory(SELECT, SelectItemModel.FACTORY);
registerReader(SELECT, SelectItemModel.READER);
registerFactory(BUNDLE_SELECTED_ITEM, BundleSelectedItemModel.FACTORY);
registerReader(BUNDLE_SELECTED_ITEM, BundleSelectedItemModel.READER);
}
public static void register(Key key, ItemModelFactory factory) {
public static void registerFactory(Key key, ItemModelFactory factory) {
Holder.Reference<ItemModelFactory> holder = ((WritableRegistry<ItemModelFactory>) BuiltInRegistries.ITEM_MODEL_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.ITEM_MODEL_FACTORY.location(), key));
holder.bindValue(factory);
}
public static void registerReader(Key key, ItemModelReader reader) {
Holder.Reference<ItemModelReader> holder = ((WritableRegistry<ItemModelReader>) BuiltInRegistries.ITEM_MODEL_READER)
.registerForHolder(new ResourceKey<>(Registries.ITEM_MODEL_READER.location(), key));
holder.bindValue(reader);
}
public static ItemModel fromMap(Map<String, Object> map) {
String type = map.getOrDefault("type", "minecraft:model").toString();
Key key = Key.withDefaultNamespace(type, "minecraft");
@@ -44,4 +61,14 @@ public class ItemModels {
}
return factory.create(map);
}
public static ItemModel fromJson(JsonObject json) {
String type = json.get("type").getAsString();
Key key = Key.withDefaultNamespace(type, "minecraft");
ItemModelReader reader = BuiltInRegistries.ITEM_MODEL_READER.getValue(key);
if (reader == null) {
throw new IllegalArgumentException("Invalid item model type: " + key);
}
return reader.read(json);
}
}

View File

@@ -1,5 +1,11 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import java.util.List;
public class ModernItemModel {
private final ItemModel itemModel;
private final boolean oversizedInGui;
@@ -11,6 +17,31 @@ public class ModernItemModel {
this.oversizedInGui = oversizedInGui;
}
public static ModernItemModel fromJson(JsonObject json) {
ItemModel model = ItemModels.fromJson(json.getAsJsonObject("model"));
return new ModernItemModel(
model,
!json.has("hand_animation_on_swap") || json.get("hand_animation_on_swap").getAsBoolean(),
json.has("oversized_in_gui") && json.get("oversized_in_gui").getAsBoolean()
);
}
public JsonObject toJson(MinecraftVersion version) {
JsonObject json = new JsonObject();
if (this.oversizedInGui) {
json.addProperty("oversized_in_gui", true);
}
if (!this.handAnimationOnSwap) {
json.addProperty("hand_animation_on_swap", false);
}
json.add("model", this.itemModel.apply(version));
return json;
}
public List<Revision> revisions() {
return this.itemModel.revisions().stream().distinct().toList();
}
public boolean handAnimationOnSwap() {
return handAnimationOnSwap;
}

View File

@@ -1,12 +1,15 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.rangedisptach.RangeDispatchProperties;
import net.momirealms.craftengine.core.pack.model.rangedisptach.RangeDispatchProperty;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.NotNull;
@@ -19,6 +22,7 @@ import java.util.Map;
public class RangeDispatchItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final RangeDispatchProperty property;
private final float scale;
private final ItemModel fallBack;
@@ -35,42 +39,42 @@ public class RangeDispatchItemModel implements ItemModel {
}
public RangeDispatchProperty property() {
return property;
return this.property;
}
public float scale() {
return scale;
return this.scale;
}
@Nullable
public ItemModel fallBack() {
return fallBack;
return this.fallBack;
}
public Map<Float, ItemModel> entries() {
return entries;
return this.entries;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
property.accept(json);
this.property.accept(json);
JsonArray array = new JsonArray();
for (Map.Entry<Float, ItemModel> entry : entries.entrySet()) {
float threshold = entry.getKey();
ItemModel model = entry.getValue();
JsonObject jo = new JsonObject();
jo.addProperty("threshold", threshold);
jo.add("model", model.get());
jo.add("model", model.apply(version));
array.add(jo);
}
json.add("entries", array);
if (scale != 1) {
json.addProperty("scale", scale);
if (this.scale != 1) {
json.addProperty("scale", this.scale);
}
if (fallBack != null) {
json.add("fallback", fallBack.get());
if (this.fallBack != null) {
json.add("fallback", this.fallBack.apply(version));
}
return json;
}
@@ -80,13 +84,25 @@ public class RangeDispatchItemModel implements ItemModel {
return ItemModels.RANGE_DISPATCH;
}
@Override
public List<Revision> revisions() {
List<Revision> versions = new ArrayList<>(4);
if (this.fallBack != null) {
versions.addAll(this.fallBack.revisions());
}
for (ItemModel model : this.entries.values()) {
versions.addAll(model.revisions());
}
return versions;
}
@Override
public List<ModelGeneration> modelsToGenerate() {
List<ModelGeneration> models = new ArrayList<>(4);
if (fallBack != null) {
models.addAll(fallBack.modelsToGenerate());
if (this.fallBack != null) {
models.addAll(this.fallBack.modelsToGenerate());
}
for (ItemModel model : entries.values()) {
for (ItemModel model : this.entries.values()) {
models.addAll(model.modelsToGenerate());
}
return models;
@@ -122,4 +138,28 @@ public class RangeDispatchItemModel implements ItemModel {
}
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
JsonArray entriesObj = json.getAsJsonArray("entries");
if (entriesObj == null) {
throw new IllegalArgumentException("entries is expected to be a JsonArray");
}
Map<Float, ItemModel> entries = new HashMap<>();
for (JsonElement entry : entriesObj) {
if (entry instanceof JsonObject entryObj) {
float threshold = entryObj.getAsJsonPrimitive("threshold").getAsFloat();
ItemModel model = ItemModels.fromJson(entryObj.getAsJsonObject("model"));
entries.put(threshold, model);
}
}
return new RangeDispatchItemModel(RangeDispatchProperties.fromJson(json),
json.has("scale") ? json.get("scale").getAsFloat() : 1f,
json.has("fallback") ? ItemModels.fromJson(json.getAsJsonObject("fallback")) : null,
entries
);
}
}
}

View File

@@ -1,12 +1,16 @@
package net.momirealms.craftengine.core.pack.model;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.select.SelectProperties;
import net.momirealms.craftengine.core.pack.model.select.SelectProperty;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import org.incendo.cloud.type.Either;
import org.jetbrains.annotations.NotNull;
@@ -19,6 +23,7 @@ import java.util.Map;
public class SelectItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final SelectProperty property;
private final Map<Either<String, List<String>>, ItemModel> whenMap;
private final ItemModel fallBack;
@@ -32,28 +37,28 @@ public class SelectItemModel implements ItemModel {
}
public SelectProperty property() {
return property;
return this.property;
}
public Map<Either<String, List<String>>, ItemModel> whenMap() {
return whenMap;
return this.whenMap;
}
public ItemModel fallBack() {
return fallBack;
return this.fallBack;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
property.accept(json);
this.property.accept(json);
JsonArray array = new JsonArray();
json.add("cases", array);
for (Map.Entry<Either<String, List<String>>, ItemModel> entry : whenMap.entrySet()) {
for (Map.Entry<Either<String, List<String>>, ItemModel> entry : this.whenMap.entrySet()) {
JsonObject item = new JsonObject();
ItemModel itemModel = entry.getValue();
item.add("model", itemModel.get());
item.add("model", itemModel.apply(version));
Either<String, List<String>> either = entry.getKey();
if (either.primary().isPresent()) {
item.addProperty("when", either.primary().get());
@@ -67,8 +72,8 @@ public class SelectItemModel implements ItemModel {
}
array.add(item);
}
if (fallBack != null) {
json.add("fallback", fallBack.get());
if (this.fallBack != null) {
json.add("fallback", this.fallBack.apply(version));
}
return json;
}
@@ -78,13 +83,25 @@ public class SelectItemModel implements ItemModel {
return ItemModels.SELECT;
}
@Override
public List<Revision> revisions() {
List<Revision> versions = new ArrayList<>();
if (this.fallBack != null) {
versions.addAll(this.fallBack.revisions());
}
for (ItemModel itemModel : this.whenMap.values()) {
versions.addAll(itemModel.revisions());
}
return versions;
}
@Override
public List<ModelGeneration> modelsToGenerate() {
List<ModelGeneration> models = new ArrayList<>(4);
if (fallBack != null) {
models.addAll(fallBack.modelsToGenerate());
if (this.fallBack != null) {
models.addAll(this.fallBack.modelsToGenerate());
}
for (ItemModel itemModel : whenMap.values()) {
for (ItemModel itemModel : this.whenMap.values()) {
models.addAll(itemModel.modelsToGenerate());
}
return models;
@@ -132,4 +149,38 @@ public class SelectItemModel implements ItemModel {
}
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
JsonArray cases = json.getAsJsonArray("cases");
if (cases == null) {
throw new IllegalArgumentException("cases is expected to be a JsonArray");
}
Map<Either<String, List<String>>, ItemModel> whenMap = new HashMap<>(cases.size());
for (JsonElement e : cases) {
if (e instanceof JsonObject caseObj) {
ItemModel model = ItemModels.fromJson(caseObj.getAsJsonObject("model"));
JsonElement whenObj = caseObj.get("when");
Either<String, List<String>> either;
if (whenObj instanceof JsonArray array) {
List<String> whens = new ArrayList<>(array.size());
for (JsonElement o : array) {
whens.add(o.toString());
}
either = Either.ofFallback(whens);
} else if (whenObj instanceof JsonPrimitive primitive) {
either = Either.ofPrimary(primitive.toString());
} else {
throw new IllegalArgumentException("when is expected to be either JsonPrimitive or JsonArray");
}
whenMap.put(either, model);
} else {
throw new IllegalArgumentException("case is expected to be a JsonObject");
}
}
return new SelectItemModel(SelectProperties.fromJson(json), whenMap, json.has("fallback") ? ItemModels.fromJson(json.getAsJsonObject("fallback")) : null);
}
}
}

View File

@@ -5,8 +5,10 @@ import net.momirealms.craftengine.core.pack.ResourceLocation;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.special.SpecialModel;
import net.momirealms.craftengine.core.pack.model.special.SpecialModels;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
@@ -16,6 +18,7 @@ import java.util.Map;
public class SpecialItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final SpecialModel specialModel;
private final String base;
private final ModelGeneration modelGeneration;
@@ -27,19 +30,19 @@ public class SpecialItemModel implements ItemModel {
}
public SpecialModel specialModel() {
return specialModel;
return this.specialModel;
}
public String base() {
return base;
return this.base;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.add("model", specialModel.get());
json.addProperty("base", base);
json.add("model", this.specialModel.apply(version));
json.addProperty("base", this.base);
return json;
}
@@ -57,6 +60,11 @@ public class SpecialItemModel implements ItemModel {
}
}
@Override
public List<Revision> revisions() {
return this.specialModel.revisions();
}
public static class Factory implements ItemModelFactory {
@Override
@@ -74,4 +82,14 @@ public class SpecialItemModel implements ItemModel {
return new SpecialItemModel(SpecialModels.fromMap(model), base, modelGeneration);
}
}
public static class Reader implements ItemModelReader {
@Override
public ItemModel read(JsonObject json) {
String base = json.get("base").getAsString();
SpecialModel sm = SpecialModels.fromJson(json.getAsJsonObject("model"));
return new SpecialItemModel(sm, base, null);
}
}
}

View File

@@ -9,6 +9,8 @@ import java.util.Map;
public class BrokenConditionProperty implements ConditionProperty, LegacyModelPredicate<Boolean> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final BrokenConditionProperty INSTANCE = new BrokenConditionProperty();
@Override
public Key type() {
@@ -34,7 +36,14 @@ public class BrokenConditionProperty implements ConditionProperty, LegacyModelPr
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
return new BrokenConditionProperty();
return INSTANCE;
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -0,0 +1,49 @@
package net.momirealms.craftengine.core.pack.model.condition;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
public class ComponentConditionProperty implements ConditionProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String predicate;
private final String value;
public ComponentConditionProperty(String predicate, String value) {
this.predicate = predicate;
this.value = value;
}
@Override
public Key type() {
return ConditionProperties.COMPONENT;
}
@Override
public void accept(JsonObject jsonObject) {
jsonObject.addProperty("property", type().toString());
jsonObject.addProperty("predicate", this.predicate);
jsonObject.addProperty("value", this.value);
}
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
String predicate = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("predicate"), "warning.config.item.model.condition.component.missing_predicate");
String value = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value"), "warning.config.item.model.condition.component.missing_value");
return new ComponentConditionProperty(predicate, value);
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
String predicate = json.get("predicate").getAsString();
String value = json.get("value").getAsString();
return new ComponentConditionProperty(predicate, value);
}
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.pack.model.condition;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -21,31 +22,52 @@ public class ConditionProperties {
public static final Key FISHING_ROD_CAST = Key.of("minecraft:fishing_rod/cast");
public static final Key HAS_COMPONENT = Key.of("minecraft:has_component");
public static final Key KEYBIND_DOWN = Key.of("minecraft:keybind_down");
public static final Key COMPONENT = Key.of("minecraft:component");
public static final Key SELECTED = Key.of("minecraft:selected");
public static final Key USING_ITEM = Key.of("minecraft:using_item");
public static final Key VIEW_ENTITY = Key.of("minecraft:view_entity");
static {
register(BROKEN, BrokenConditionProperty.FACTORY);
register(BUNDLE_HAS_SELECTED_ITEM, SimpleConditionProperty.FACTORY);
register(CARRIED, SimpleConditionProperty.FACTORY);
register(DAMAGED, DamagedConditionProperty.FACTORY);
register(EXTENDED_VIEW, SimpleConditionProperty.FACTORY);
register(FISHING_ROD_CAST, RodCastConditionProperty.FACTORY);
register(SELECTED, SimpleConditionProperty.FACTORY);
register(USING_ITEM, UsingItemConditionProperty.FACTORY);
register(VIEW_ENTITY, SimpleConditionProperty.FACTORY);
register(CUSTOM_MODEL_DATA, CustomModelDataConditionProperty.FACTORY);
register(HAS_COMPONENT, HasComponentConditionProperty.FACTORY);
register(KEYBIND_DOWN, KeyBindDownConditionProperty.FACTORY);
registerFactory(BROKEN, BrokenConditionProperty.FACTORY);
registerReader(BROKEN, BrokenConditionProperty.READER);
registerFactory(BUNDLE_HAS_SELECTED_ITEM, SimpleConditionProperty.FACTORY);
registerReader(BUNDLE_HAS_SELECTED_ITEM, SimpleConditionProperty.READER);
registerFactory(CARRIED, SimpleConditionProperty.FACTORY);
registerReader(CARRIED, SimpleConditionProperty.READER);
registerFactory(DAMAGED, DamagedConditionProperty.FACTORY);
registerReader(DAMAGED, DamagedConditionProperty.READER);
registerFactory(EXTENDED_VIEW, SimpleConditionProperty.FACTORY);
registerReader(EXTENDED_VIEW, SimpleConditionProperty.READER);
registerFactory(FISHING_ROD_CAST, RodCastConditionProperty.FACTORY);
registerReader(FISHING_ROD_CAST, RodCastConditionProperty.READER);
registerFactory(SELECTED, SimpleConditionProperty.FACTORY);
registerReader(SELECTED, SimpleConditionProperty.READER);
registerFactory(USING_ITEM, UsingItemConditionProperty.FACTORY);
registerReader(USING_ITEM, UsingItemConditionProperty.READER);
registerFactory(VIEW_ENTITY, SimpleConditionProperty.FACTORY);
registerReader(VIEW_ENTITY, SimpleConditionProperty.READER);
registerFactory(CUSTOM_MODEL_DATA, CustomModelDataConditionProperty.FACTORY);
registerReader(CUSTOM_MODEL_DATA, CustomModelDataConditionProperty.READER);
registerFactory(HAS_COMPONENT, HasComponentConditionProperty.FACTORY);
registerReader(HAS_COMPONENT, HasComponentConditionProperty.READER);
registerFactory(KEYBIND_DOWN, KeyBindDownConditionProperty.FACTORY);
registerReader(KEYBIND_DOWN, KeyBindDownConditionProperty.READER);
registerFactory(COMPONENT, ComponentConditionProperty.FACTORY);
registerReader(COMPONENT, ComponentConditionProperty.READER);
}
public static void register(Key key, ConditionPropertyFactory factory) {
public static void registerFactory(Key key, ConditionPropertyFactory factory) {
Holder.Reference<ConditionPropertyFactory> holder = ((WritableRegistry<ConditionPropertyFactory>) BuiltInRegistries.CONDITION_PROPERTY_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.CONDITION_PROPERTY_FACTORY.location(), key));
holder.bindValue(factory);
}
public static void registerReader(Key key, ConditionPropertyReader reader) {
Holder.Reference<ConditionPropertyReader> holder = ((WritableRegistry<ConditionPropertyReader>) BuiltInRegistries.CONDITION_PROPERTY_READER)
.registerForHolder(new ResourceKey<>(Registries.CONDITION_PROPERTY_READER.location(), key));
holder.bindValue(reader);
}
public static ConditionProperty fromMap(Map<String, Object> map) {
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("property"), "warning.config.item.model.condition.missing_property");
Key key = Key.withDefaultNamespace(type, "minecraft");
@@ -55,4 +77,14 @@ public class ConditionProperties {
}
return factory.create(map);
}
public static ConditionProperty fromJson(JsonObject json) {
String type = json.get("property").getAsString();
Key key = Key.withDefaultNamespace(type, "minecraft");
ConditionPropertyReader reader = BuiltInRegistries.CONDITION_PROPERTY_READER.getValue(key);
if (reader == null) {
throw new IllegalArgumentException("Invalid condition property type: " + key);
}
return reader.read(json);
}
}

View File

@@ -0,0 +1,8 @@
package net.momirealms.craftengine.core.pack.model.condition;
import com.google.gson.JsonObject;
public interface ConditionPropertyReader {
ConditionProperty read(JsonObject json);
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class CustomModelDataConditionProperty implements ConditionProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final int index;
public CustomModelDataConditionProperty(int index) {
@@ -22,16 +23,23 @@ public class CustomModelDataConditionProperty implements ConditionProperty {
@Override
public void accept(JsonObject jsonObject) {
jsonObject.addProperty("property", type().toString());
if (index != 0)
jsonObject.addProperty("index", index);
if (this.index != 0)
jsonObject.addProperty("index", this.index);
}
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
int index = ResourceConfigUtils.getAsInt(arguments.getOrDefault("index", 0), "index");
return new CustomModelDataConditionProperty(index);
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
int index = json.has("index") ? json.get("index").getAsInt() : 0;
return new CustomModelDataConditionProperty(index);
}
}
}

View File

@@ -8,6 +8,8 @@ import java.util.Map;
public class DamagedConditionProperty implements ConditionProperty, LegacyModelPredicate<Boolean> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final DamagedConditionProperty INSTANCE = new DamagedConditionProperty();
@Override
public Key type() {
@@ -32,7 +34,14 @@ public class DamagedConditionProperty implements ConditionProperty, LegacyModelP
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
return new DamagedConditionProperty();
return INSTANCE;
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class HasComponentConditionProperty implements ConditionProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String component;
private final boolean ignoreDefault;
@@ -47,4 +48,13 @@ public class HasComponentConditionProperty implements ConditionProperty {
return new HasComponentConditionProperty(componentObj, ignoreDefault);
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
String component = json.get("component").getAsString();
boolean ignoreDefault = json.has("ignore_default") && json.get("ignore_default").getAsBoolean();
return new HasComponentConditionProperty(component, ignoreDefault);
}
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class KeyBindDownConditionProperty implements ConditionProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String keybind;
public KeyBindDownConditionProperty(String keybind) {
@@ -26,11 +27,18 @@ public class KeyBindDownConditionProperty implements ConditionProperty {
}
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
String keybindObj = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("keybind"), "warning.config.item.model.condition.keybind.missing");
String keybindObj = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("keybind"), "warning.config.item.model.condition.keybind.missing_keybind");
return new KeyBindDownConditionProperty(keybindObj);
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
String keybind = json.get("keybind").getAsString();
return new KeyBindDownConditionProperty(keybind);
}
}
}

View File

@@ -9,6 +9,8 @@ import java.util.Map;
public class RodCastConditionProperty implements ConditionProperty, LegacyModelPredicate<Boolean> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final RodCastConditionProperty INSTANCE = new RodCastConditionProperty();
@Override
public Key type() {
@@ -34,7 +36,14 @@ public class RodCastConditionProperty implements ConditionProperty, LegacyModelP
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
return new RodCastConditionProperty();
return INSTANCE;
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -7,6 +7,7 @@ import java.util.Map;
public class SimpleConditionProperty implements ConditionProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Key type;
public SimpleConditionProperty(Key type) {
@@ -30,4 +31,11 @@ public class SimpleConditionProperty implements ConditionProperty {
return new SimpleConditionProperty(type);
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
return new SimpleConditionProperty(Key.of(json.get("property").toString()));
}
}
}

View File

@@ -9,6 +9,8 @@ import java.util.Map;
public class UsingItemConditionProperty implements ConditionProperty, LegacyModelPredicate<Boolean> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final UsingItemConditionProperty INSTANCE = new UsingItemConditionProperty();
@Override
public Key type() {
@@ -37,7 +39,14 @@ public class UsingItemConditionProperty implements ConditionProperty, LegacyMode
public static class Factory implements ConditionPropertyFactory {
@Override
public ConditionProperty create(Map<String, Object> arguments) {
return new UsingItemConditionProperty();
return INSTANCE;
}
}
public static class Reader implements ConditionPropertyReader {
@Override
public ConditionProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -8,10 +8,13 @@ import java.util.Map;
public class CompassRangeDispatchProperty implements RangeDispatchProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String target;
private final boolean wobble;
public CompassRangeDispatchProperty(String target) {
public CompassRangeDispatchProperty(String target, boolean wobble) {
this.target = target;
this.wobble = wobble;
}
@Override
@@ -22,15 +25,27 @@ public class CompassRangeDispatchProperty implements RangeDispatchProperty {
@Override
public void accept(JsonObject jsonObject) {
jsonObject.addProperty("property", type().toString());
jsonObject.addProperty("target", target);
jsonObject.addProperty("target", this.target);
if (!this.wobble) {
jsonObject.addProperty("wobble", false);
}
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
String targetObj = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("target"), "warning.config.item.model.range_dispatch.compass.missing_target");
return new CompassRangeDispatchProperty(targetObj);
boolean wobble = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("wobble", true), "wobble");
return new CompassRangeDispatchProperty(targetObj, wobble);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
String target = json.get("target").getAsString();
boolean wobble = !json.has("wobble") || json.get("wobble").getAsBoolean();
return new CompassRangeDispatchProperty(target, wobble);
}
}
}

View File

@@ -9,6 +9,8 @@ import java.util.Map;
public class CrossBowPullingRangeDispatchProperty implements RangeDispatchProperty, LegacyModelPredicate<Float> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final CrossBowPullingRangeDispatchProperty INSTANCE = new CrossBowPullingRangeDispatchProperty();
@Override
public void accept(JsonObject jsonObject) {
@@ -32,10 +34,16 @@ public class CrossBowPullingRangeDispatchProperty implements RangeDispatchProper
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
return new CrossBowPullingRangeDispatchProperty();
return INSTANCE;
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -9,6 +9,7 @@ import java.util.Map;
public class CustomModelDataRangeDispatchProperty implements RangeDispatchProperty, LegacyModelPredicate<Float> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final int index;
public CustomModelDataRangeDispatchProperty(int index) {
@@ -37,11 +38,18 @@ public class CustomModelDataRangeDispatchProperty implements RangeDispatchProper
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
int index = ResourceConfigUtils.getAsInt(arguments.getOrDefault("index", 0), "index");
return new CustomModelDataRangeDispatchProperty(index);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
int index = json.has("index") ? json.get("index").getAsInt() : 0;
return new CustomModelDataRangeDispatchProperty(index);
}
}
}

View File

@@ -9,6 +9,7 @@ import java.util.Map;
public class DamageRangeDispatchProperty implements RangeDispatchProperty, LegacyModelPredicate<Float> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final boolean normalize;
public DamageRangeDispatchProperty(boolean normalize) {
@@ -41,11 +42,18 @@ public class DamageRangeDispatchProperty implements RangeDispatchProperty, Legac
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
boolean normalize = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("normalize", true), "normalize");
return new DamageRangeDispatchProperty(normalize);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
boolean normalize = !json.has("normalize") || json.get("normalize").getAsBoolean();
return new DamageRangeDispatchProperty(normalize);
}
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class NormalizeRangeDispatchProperty implements RangeDispatchProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Key type;
private final boolean normalize;
@@ -30,7 +31,6 @@ public class NormalizeRangeDispatchProperty implements RangeDispatchProperty {
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
Key type = Key.of(arguments.get("property").toString());
@@ -38,4 +38,13 @@ public class NormalizeRangeDispatchProperty implements RangeDispatchProperty {
return new NormalizeRangeDispatchProperty(type, normalize);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
Key type = Key.of(json.get("property").toString());
boolean normalize = !json.has("normalize") || json.get("normalize").getAsBoolean();
return new NormalizeRangeDispatchProperty(type, normalize);
}
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.pack.model.rangedisptach;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -24,24 +25,40 @@ public class RangeDispatchProperties {
public static final Key USE_DURATION = Key.of("minecraft:use_duration");
static {
register(BUNDLE_FULLNESS, SimpleRangeDispatchProperty.FACTORY);
register(COOLDOWN, SimpleRangeDispatchProperty.FACTORY);
register(CROSSBOW_PULL, CrossBowPullingRangeDispatchProperty.FACTORY);
register(COMPASS, CompassRangeDispatchProperty.FACTORY);
register(COUNT, NormalizeRangeDispatchProperty.FACTORY);
register(DAMAGE, DamageRangeDispatchProperty.FACTORY);
register(CUSTOM_MODEL_DATA, CustomModelDataRangeDispatchProperty.FACTORY);
register(TIME, TimeRangeDispatchProperty.FACTORY);
register(USE_CYCLE, UseCycleRangeDispatchProperty.FACTORY);
register(USE_DURATION, UseDurationRangeDispatchProperty.FACTORY);
registerFactory(BUNDLE_FULLNESS, SimpleRangeDispatchProperty.FACTORY);
registerReader(BUNDLE_FULLNESS, SimpleRangeDispatchProperty.READER);
registerFactory(COOLDOWN, SimpleRangeDispatchProperty.FACTORY);
registerReader(COOLDOWN, SimpleRangeDispatchProperty.READER);
registerFactory(CROSSBOW_PULL, CrossBowPullingRangeDispatchProperty.FACTORY);
registerReader(CROSSBOW_PULL, CrossBowPullingRangeDispatchProperty.READER);
registerFactory(COMPASS, CompassRangeDispatchProperty.FACTORY);
registerReader(COMPASS, CompassRangeDispatchProperty.READER);
registerFactory(COUNT, NormalizeRangeDispatchProperty.FACTORY);
registerReader(COUNT, NormalizeRangeDispatchProperty.READER);
registerFactory(DAMAGE, DamageRangeDispatchProperty.FACTORY);
registerReader(DAMAGE, DamageRangeDispatchProperty.READER);
registerFactory(CUSTOM_MODEL_DATA, CustomModelDataRangeDispatchProperty.FACTORY);
registerReader(CUSTOM_MODEL_DATA, CustomModelDataRangeDispatchProperty.READER);
registerFactory(TIME, TimeRangeDispatchProperty.FACTORY);
registerReader(TIME, TimeRangeDispatchProperty.READER);
registerFactory(USE_CYCLE, UseCycleRangeDispatchProperty.FACTORY);
registerReader(USE_CYCLE, UseCycleRangeDispatchProperty.READER);
registerFactory(USE_DURATION, UseDurationRangeDispatchProperty.FACTORY);
registerReader(USE_DURATION, UseDurationRangeDispatchProperty.READER);
}
public static void register(Key key, RangeDispatchPropertyFactory factory) {
public static void registerFactory(Key key, RangeDispatchPropertyFactory factory) {
Holder.Reference<RangeDispatchPropertyFactory> holder = ((WritableRegistry<RangeDispatchPropertyFactory>) BuiltInRegistries.RANGE_DISPATCH_PROPERTY_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.RANGE_DISPATCH_PROPERTY_FACTORY.location(), key));
holder.bindValue(factory);
}
public static void registerReader(Key key, RangeDispatchPropertyReader reader) {
Holder.Reference<RangeDispatchPropertyReader> holder = ((WritableRegistry<RangeDispatchPropertyReader>) BuiltInRegistries.RANGE_DISPATCH_PROPERTY_READER)
.registerForHolder(new ResourceKey<>(Registries.RANGE_DISPATCH_PROPERTY_READER.location(), key));
holder.bindValue(reader);
}
public static RangeDispatchProperty fromMap(Map<String, Object> map) {
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("property"), "warning.config.item.model.range_dispatch.missing_property");
Key key = Key.withDefaultNamespace(type, "minecraft");
@@ -51,4 +68,14 @@ public class RangeDispatchProperties {
}
return factory.create(map);
}
public static RangeDispatchProperty fromJson(JsonObject json) {
String type = json.get("property").getAsString();
Key key = Key.withDefaultNamespace(type, "minecraft");
RangeDispatchPropertyReader reader = BuiltInRegistries.RANGE_DISPATCH_PROPERTY_READER.getValue(key);
if (reader == null) {
throw new IllegalArgumentException("Invalid range dispatch property type: " + key);
}
return reader.read(json);
}
}

View File

@@ -0,0 +1,8 @@
package net.momirealms.craftengine.core.pack.model.rangedisptach;
import com.google.gson.JsonObject;
public interface RangeDispatchPropertyReader {
RangeDispatchProperty read(JsonObject json);
}

View File

@@ -7,6 +7,7 @@ import java.util.Map;
public class SimpleRangeDispatchProperty implements RangeDispatchProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Key type;
public SimpleRangeDispatchProperty(Key type) {
@@ -24,11 +25,18 @@ public class SimpleRangeDispatchProperty implements RangeDispatchProperty {
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
Key type = Key.of(arguments.get("property").toString());
return new SimpleRangeDispatchProperty(type);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
Key type = Key.of(json.get("property").toString());
return new SimpleRangeDispatchProperty(type);
}
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class TimeRangeDispatchProperty implements RangeDispatchProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String source;
private final boolean wobble;
@@ -31,7 +32,6 @@ public class TimeRangeDispatchProperty implements RangeDispatchProperty {
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
String sourceObj = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("source"), "warning.config.item.model.range_dispatch.time.missing_source");
@@ -39,4 +39,13 @@ public class TimeRangeDispatchProperty implements RangeDispatchProperty {
return new TimeRangeDispatchProperty(sourceObj, wobble);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
String source = json.get("source").getAsString();
boolean wobble = !json.has("wobble") || json.get("wobble").getAsBoolean();
return new TimeRangeDispatchProperty(source, wobble);
}
}
}

View File

@@ -8,9 +8,10 @@ import java.util.Map;
public class UseCycleRangeDispatchProperty implements RangeDispatchProperty {
public static final Factory FACTORY = new Factory();
private final int period;
public static final Reader READER = new Reader();
private final float period;
public UseCycleRangeDispatchProperty(int period) {
public UseCycleRangeDispatchProperty(float period) {
this.period = period;
}
@@ -26,10 +27,17 @@ public class UseCycleRangeDispatchProperty implements RangeDispatchProperty {
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
int period = ResourceConfigUtils.getAsInt(arguments.getOrDefault("period", 0), "period");
float period = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("period", 0), "period");
return new UseCycleRangeDispatchProperty(period);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
float period = json.has("period") ? json.get("period").getAsFloat() : 1.0f;
return new UseCycleRangeDispatchProperty(period);
}
}

View File

@@ -10,6 +10,7 @@ import java.util.Map;
public class UseDurationRangeDispatchProperty implements RangeDispatchProperty, LegacyModelPredicate<Float> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final boolean remaining;
public UseDurationRangeDispatchProperty(boolean remaining) {
@@ -41,11 +42,18 @@ public class UseDurationRangeDispatchProperty implements RangeDispatchProperty,
}
public static class Factory implements RangeDispatchPropertyFactory {
@Override
public RangeDispatchProperty create(Map<String, Object> arguments) {
boolean remaining = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("remaining", false), "remaining");
return new UseDurationRangeDispatchProperty(remaining);
}
}
public static class Reader implements RangeDispatchPropertyReader {
@Override
public RangeDispatchProperty read(JsonObject json) {
boolean remaining = json.has("remaining") && json.get("remaining").getAsBoolean();
return new UseDurationRangeDispatchProperty(remaining);
}
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class BlockStateSelectProperty implements SelectProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String blockStateProperty;
public BlockStateSelectProperty(String blockStateProperty) {
@@ -26,11 +27,18 @@ public class BlockStateSelectProperty implements SelectProperty {
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
String property = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("block-state-property"), "warning.config.item.model.select.block_state.missing_property");
return new BlockStateSelectProperty(property);
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
String property = json.get("block_state_property").getAsString();
return new BlockStateSelectProperty(property);
}
}
}

View File

@@ -9,6 +9,8 @@ import java.util.Map;
public class ChargeTypeSelectProperty implements SelectProperty, LegacyModelPredicate<String> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final ChargeTypeSelectProperty INSTANCE = new ChargeTypeSelectProperty();
@Override
public Key type() {
@@ -33,10 +35,16 @@ public class ChargeTypeSelectProperty implements SelectProperty, LegacyModelPred
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
return new ChargeTypeSelectProperty();
return INSTANCE;
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -0,0 +1,44 @@
package net.momirealms.craftengine.core.pack.model.select;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
public class ComponentSelectProperty implements SelectProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String component;
public ComponentSelectProperty(String component) {
this.component = component;
}
@Override
public Key type() {
return SelectProperties.COMPONENT;
}
@Override
public void accept(JsonObject jsonObject) {
jsonObject.addProperty("property", type().toString());
jsonObject.addProperty("component", this.component);
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
String component = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("component"), "warning.config.item.model.select.component.missing_component");
return new ComponentSelectProperty(component);
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
String component = json.get("component").getAsString();
return new ComponentSelectProperty(component);
}
}
}

View File

@@ -8,6 +8,7 @@ import java.util.Map;
public class CustomModelDataSelectProperty implements SelectProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final int index;
public CustomModelDataSelectProperty(int index) {
@@ -26,11 +27,18 @@ public class CustomModelDataSelectProperty implements SelectProperty {
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
int index = ResourceConfigUtils.getAsInt(arguments.getOrDefault("index", 0), "index");
return new CustomModelDataSelectProperty(index);
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
int index = json.has("index") ? json.get("index").getAsInt() : 0;
return new CustomModelDataSelectProperty(index);
}
}
}

View File

@@ -10,6 +10,7 @@ import java.util.Map;
public class LocalTimeSelectProperty implements SelectProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String pattern;
private final String locale;
private final String timeZone;
@@ -30,17 +31,16 @@ public class LocalTimeSelectProperty implements SelectProperty {
@Override
public void accept(JsonObject jsonObject) {
jsonObject.addProperty("property", type().toString());
jsonObject.addProperty("pattern", pattern);
if (locale != null) {
jsonObject.addProperty("locale", locale);
jsonObject.addProperty("pattern", this.pattern);
if (this.locale != null) {
jsonObject.addProperty("locale", this.locale);
}
if (timeZone != null) {
jsonObject.addProperty("time_zone", timeZone);
if (this.timeZone != null) {
jsonObject.addProperty("time_zone", this.timeZone);
}
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
String pattern = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("pattern"), "warning.config.item.model.select.local_time.missing_pattern");
@@ -49,4 +49,14 @@ public class LocalTimeSelectProperty implements SelectProperty {
return new LocalTimeSelectProperty(pattern, locale, timeZone);
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
String pattern = json.get("pattern").getAsString();
String locale = json.has("locale") ? json.get("locale").getAsString() : null;
String timeZone = json.has("time_zone") ? json.get("time_zone").getAsString() : null;
return new LocalTimeSelectProperty(pattern, locale, timeZone);
}
}
}

View File

@@ -8,6 +8,8 @@ import java.util.Map;
public class MainHandSelectProperty implements SelectProperty, LegacyModelPredicate<String> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final MainHandSelectProperty INSTANCE = new MainHandSelectProperty();
@Override
public Key type() {
@@ -31,10 +33,16 @@ public class MainHandSelectProperty implements SelectProperty, LegacyModelPredic
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
return new MainHandSelectProperty();
return INSTANCE;
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.pack.model.select;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -21,25 +22,43 @@ public class SelectProperties {
public static final Key LOCAL_TIME = Key.of("minecraft:local_time");
public static final Key MAIN_HAND = Key.of("minecraft:main_hand");
public static final Key TRIM_MATERIAL = Key.of("minecraft:trim_material");
public static final Key COMPONENT = Key.of("minecraft:component");
static {
register(CHARGE_TYPE, ChargeTypeSelectProperty.FACTORY);
register(CONTEXT_DIMENSION, SimpleSelectProperty.FACTORY);
register(CONTEXT_ENTITY_TYPE, SimpleSelectProperty.FACTORY);
register(DISPLAY_CONTEXT, SimpleSelectProperty.FACTORY);
register(MAIN_HAND, MainHandSelectProperty.FACTORY);
register(TRIM_MATERIAL, TrimMaterialSelectProperty.FACTORY);
register(BLOCK_STATE, BlockStateSelectProperty.FACTORY);
register(CUSTOM_MODEL_DATA, CustomModelDataSelectProperty.FACTORY);
register(LOCAL_TIME, LocalTimeSelectProperty.FACTORY);
registerFactory(CHARGE_TYPE, ChargeTypeSelectProperty.FACTORY);
registerReader(CHARGE_TYPE, ChargeTypeSelectProperty.READER);
registerFactory(CONTEXT_DIMENSION, SimpleSelectProperty.FACTORY);
registerReader(CONTEXT_DIMENSION, SimpleSelectProperty.READER);
registerFactory(CONTEXT_ENTITY_TYPE, SimpleSelectProperty.FACTORY);
registerReader(CONTEXT_ENTITY_TYPE, SimpleSelectProperty.READER);
registerFactory(DISPLAY_CONTEXT, SimpleSelectProperty.FACTORY);
registerReader(DISPLAY_CONTEXT, SimpleSelectProperty.READER);
registerFactory(MAIN_HAND, MainHandSelectProperty.FACTORY);
registerReader(MAIN_HAND, MainHandSelectProperty.READER);
registerFactory(TRIM_MATERIAL, TrimMaterialSelectProperty.FACTORY);
registerReader(TRIM_MATERIAL, TrimMaterialSelectProperty.READER);
registerFactory(BLOCK_STATE, BlockStateSelectProperty.FACTORY);
registerReader(BLOCK_STATE, BlockStateSelectProperty.READER);
registerFactory(CUSTOM_MODEL_DATA, CustomModelDataSelectProperty.FACTORY);
registerReader(CUSTOM_MODEL_DATA, CustomModelDataSelectProperty.READER);
registerFactory(LOCAL_TIME, LocalTimeSelectProperty.FACTORY);
registerReader(LOCAL_TIME, LocalTimeSelectProperty.READER);
registerFactory(COMPONENT, ComponentSelectProperty.FACTORY);
registerReader(COMPONENT, ComponentSelectProperty.READER);
}
public static void register(Key key, SelectPropertyFactory factory) {
public static void registerFactory(Key key, SelectPropertyFactory factory) {
Holder.Reference<SelectPropertyFactory> holder = ((WritableRegistry<SelectPropertyFactory>) BuiltInRegistries.SELECT_PROPERTY_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.SELECT_PROPERTY_FACTORY.location(), key));
holder.bindValue(factory);
}
public static void registerReader(Key key, SelectPropertyReader reader) {
Holder.Reference<SelectPropertyReader> holder = ((WritableRegistry<SelectPropertyReader>) BuiltInRegistries.SELECT_PROPERTY_READER)
.registerForHolder(new ResourceKey<>(Registries.SELECT_PROPERTY_READER.location(), key));
holder.bindValue(reader);
}
public static SelectProperty fromMap(Map<String, Object> map) {
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("property"), "warning.config.item.model.select.missing_property");
Key key = Key.withDefaultNamespace(type, "minecraft");
@@ -49,4 +68,14 @@ public class SelectProperties {
}
return factory.create(map);
}
public static SelectProperty fromJson(JsonObject json) {
String type = json.get("property").getAsString();
Key key = Key.withDefaultNamespace(type, "minecraft");
SelectPropertyReader reader = BuiltInRegistries.SELECT_PROPERTY_READER.getValue(key);
if (reader == null) {
throw new IllegalArgumentException("Invalid select property type: " + key);
}
return reader.read(json);
}
}

View File

@@ -0,0 +1,8 @@
package net.momirealms.craftengine.core.pack.model.select;
import com.google.gson.JsonObject;
public interface SelectPropertyReader {
SelectProperty read(JsonObject json);
}

View File

@@ -7,6 +7,7 @@ import java.util.Map;
public class SimpleSelectProperty implements SelectProperty {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Key type;
public SimpleSelectProperty(Key type) {
@@ -24,11 +25,18 @@ public class SimpleSelectProperty implements SelectProperty {
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
Key type = Key.of(arguments.get("property").toString());
return new SimpleSelectProperty(type);
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
Key type = Key.of(json.get("property").toString());
return new SimpleSelectProperty(type);
}
}
}

View File

@@ -9,6 +9,8 @@ import java.util.Map;
public class TrimMaterialSelectProperty implements SelectProperty, LegacyModelPredicate<String> {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final TrimMaterialSelectProperty INSTANCE = new TrimMaterialSelectProperty();
private static final Map<String, Float> LEGACY_TRIM_DATA = new HashMap<>();
static {
LEGACY_TRIM_DATA.put("minecraft:quartz", 0.1f);
@@ -58,10 +60,16 @@ public class TrimMaterialSelectProperty implements SelectProperty, LegacyModelPr
}
public static class Factory implements SelectPropertyFactory {
@Override
public SelectProperty create(Map<String, Object> arguments) {
return new TrimMaterialSelectProperty();
return INSTANCE;
}
}
public static class Reader implements SelectPropertyReader {
@Override
public SelectProperty read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -1,13 +1,17 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Map;
public class BannerSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String color;
public BannerSpecialModel(String color) {
@@ -20,19 +24,31 @@ public class BannerSpecialModel implements SpecialModel {
}
@Override
public JsonObject get() {
public List<Revision> revisions() {
return List.of();
}
@Override
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("color", color);
json.addProperty("color", this.color);
return json;
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
String color = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("color"), "warning.config.item.model.special.banner.missing_color");
return new BannerSpecialModel(color);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
String color = json.get("color").getAsString();
return new BannerSpecialModel(color);
}
}
}

View File

@@ -1,13 +1,17 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Map;
public class BedSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String texture;
public BedSpecialModel(String texture) {
@@ -20,19 +24,31 @@ public class BedSpecialModel implements SpecialModel {
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("texture", texture);
return json;
}
public static class Factory implements SpecialModelFactory {
@Override
public List<Revision> revisions() {
return List.of();
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
String color = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("texture"), "warning.config.item.model.special.bed.missing_texture");
return new BedSpecialModel(color);
String texture = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("texture"), "warning.config.item.model.special.bed.missing_texture");
return new BedSpecialModel(texture);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
String texture = json.get("texture").getAsString();
return new BedSpecialModel(texture);
}
}
}

View File

@@ -1,14 +1,18 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Map;
public class ChestSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String texture;
private final float openness;
@@ -23,7 +27,12 @@ public class ChestSpecialModel implements SpecialModel {
}
@Override
public JsonObject get() {
public List<Revision> revisions() {
return List.of();
}
@Override
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("texture", texture);
@@ -34,7 +43,6 @@ public class ChestSpecialModel implements SpecialModel {
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
float openness = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("openness", 0), "openness");
@@ -45,4 +53,12 @@ public class ChestSpecialModel implements SpecialModel {
return new ChestSpecialModel(texture, openness);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
float openness = json.has("openness") ? json.get("openness").getAsFloat() : 0;
return new ChestSpecialModel(json.get("texture").getAsString(), openness);
}
}
}

View File

@@ -1,19 +1,23 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class HeadSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String kind;
private final String texture;
private final int animation;
private final float animation;
public HeadSpecialModel(String kind, String texture, int animation) {
public HeadSpecialModel(String kind, String texture, float animation) {
this.kind = kind;
this.texture = texture;
this.animation = animation;
@@ -25,26 +29,40 @@ public class HeadSpecialModel implements SpecialModel {
}
@Override
public JsonObject get() {
public List<Revision> revisions() {
return List.of();
}
@Override
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("kind", kind);
if (texture != null) {
json.addProperty("texture", texture);
json.addProperty("kind", this.kind);
if (this.texture != null) {
json.addProperty("texture", this.texture);
}
if (animation != 0) {
json.addProperty("animation", animation);
if (this.animation != 0) {
json.addProperty("animation", this.animation);
}
return json;
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
String kind = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("kind"), "warning.config.item.model.special.head.missing_kind");
String texture = Optional.ofNullable(arguments.get("texture")).map(String::valueOf).orElse(null);
int animation = ResourceConfigUtils.getAsInt(arguments.getOrDefault("animation", 0), "animation");
float animation = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("animation", 0), "animation");
return new HeadSpecialModel(kind, texture, animation);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
String kind = json.get("kind").getAsString();
String texture = json.has("texture") ? json.get("texture").getAsString() : null;
float animation = json.has("animation") ? json.get("animation").getAsFloat() : 0f;
return new HeadSpecialModel(kind, texture, animation);
}
}

View File

@@ -0,0 +1,56 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.pack.revision.Revisions;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MinecraftVersions;
import java.util.List;
import java.util.Map;
public class PlayerHeadSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
public static final PlayerHeadSpecialModel INSTANCE = new PlayerHeadSpecialModel();
public PlayerHeadSpecialModel() {
}
@Override
public Key type() {
return SpecialModels.PLAYER_HEAD;
}
@Override
public List<Revision> revisions() {
return List.of(Revisions.SINCE_1_21_6);
}
@Override
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
if (version.isAtOrAbove(MinecraftVersions.V1_21_6)) {
json.addProperty("type", type().toString());
} else {
json.addProperty("type", SpecialModels.HEAD.toString());
json.addProperty("kind", "player");
}
return json;
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
return INSTANCE;
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
return INSTANCE;
}
}
}

View File

@@ -1,18 +1,22 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
public class ShulkerBoxSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final String texture;
private final float openness;
private final Direction orientation;
@@ -23,13 +27,18 @@ public class ShulkerBoxSpecialModel implements SpecialModel {
this.orientation = orientation;
}
@Override
public List<Revision> revisions() {
return List.of();
}
@Override
public Key type() {
return SpecialModels.SHULKER_BOX;
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("texture", texture);
@@ -41,7 +50,6 @@ public class ShulkerBoxSpecialModel implements SpecialModel {
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
float openness = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("openness", 0), "openness");
@@ -53,4 +61,14 @@ public class ShulkerBoxSpecialModel implements SpecialModel {
return new ShulkerBoxSpecialModel(texture, openness, orientation);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
float openness = json.has("openness") ? json.get("openness").getAsFloat() : 0f;
Direction orientation = json.has("orientation") ? Direction.valueOf(json.get("orientation").getAsString().toUpperCase(Locale.ENGLISH)) : null;
String texture = json.get("texture").getAsString();
return new ShulkerBoxSpecialModel(texture, openness, orientation);
}
}
}

View File

@@ -1,13 +1,17 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Map;
public class SignSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Key type;
private final String woodType;
private final String texture;
@@ -24,7 +28,12 @@ public class SignSpecialModel implements SpecialModel {
}
@Override
public JsonObject get() {
public List<Revision> revisions() {
return List.of();
}
@Override
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("wood_type", woodType);
@@ -33,7 +42,6 @@ public class SignSpecialModel implements SpecialModel {
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
Key type = Key.of(arguments.get("type").toString());
@@ -42,4 +50,14 @@ public class SignSpecialModel implements SpecialModel {
return new SignSpecialModel(type, woodType, texture);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
Key type = Key.of(json.get("type").toString());
String woodType = json.get("wood_type").getAsString();
String texture = json.get("texture").getAsString();
return new SignSpecialModel(type, woodType, texture);
}
}
}

View File

@@ -1,12 +1,16 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import java.util.List;
import java.util.Map;
public class SimpleSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Key type;
public SimpleSpecialModel(Key type) {
@@ -19,18 +23,30 @@ public class SimpleSpecialModel implements SpecialModel {
}
@Override
public JsonObject get() {
public JsonObject apply(MinecraftVersion version) {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
return json;
}
public static class Factory implements SpecialModelFactory {
@Override
public List<Revision> revisions() {
return List.of();
}
public static class Factory implements SpecialModelFactory {
@Override
public SpecialModel create(Map<String, Object> arguments) {
Key type = Key.of(arguments.get("type").toString());
return new SimpleSpecialModel(type);
}
}
public static class Reader implements SpecialModelReader {
@Override
public SpecialModel read(JsonObject json) {
Key type = Key.of(json.get("type").toString());
return new SimpleSpecialModel(type);
}
}
}

View File

@@ -1,11 +1,16 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.revision.Revision;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import java.util.function.Supplier;
import java.util.List;
import java.util.function.Function;
public interface SpecialModel extends Supplier<JsonObject> {
public interface SpecialModel extends Function<MinecraftVersion, JsonObject> {
Key type();
List<Revision> revisions();
}

View File

@@ -0,0 +1,8 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
public interface SpecialModelReader {
SpecialModel read(JsonObject json);
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.pack.model.special;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -23,26 +24,47 @@ public class SpecialModels {
public static final Key SHULKER_BOX = Key.of("minecraft:shulker_box");
public static final Key STANDING_SIGN = Key.of("minecraft:standing_sign");
public static final Key TRIDENT = Key.of("minecraft:trident");
public static final Key PLAYER_HEAD = Key.of("minecraft:player_head");
static {
register(TRIDENT, SimpleSpecialModel.FACTORY);
register(DECORATED_POT, SimpleSpecialModel.FACTORY);
register(CONDUIT, SimpleSpecialModel.FACTORY);
register(SHIELD, SimpleSpecialModel.FACTORY);
register(HANGING_SIGN, SignSpecialModel.FACTORY);
register(STANDING_SIGN, SignSpecialModel.FACTORY);
register(CHEST, ChestSpecialModel.FACTORY);
register(BANNER, BannerSpecialModel.FACTORY);
register(BED, BedSpecialModel.FACTORY);
register(HEAD, HeadSpecialModel.FACTORY);
registerFactory(TRIDENT, SimpleSpecialModel.FACTORY);
registerReader(TRIDENT, SimpleSpecialModel.READER);
registerFactory(DECORATED_POT, SimpleSpecialModel.FACTORY);
registerReader(DECORATED_POT, SimpleSpecialModel.READER);
registerFactory(CONDUIT, SimpleSpecialModel.FACTORY);
registerReader(CONDUIT, SimpleSpecialModel.READER);
registerFactory(SHIELD, SimpleSpecialModel.FACTORY);
registerReader(SHIELD, SimpleSpecialModel.READER);
registerFactory(HANGING_SIGN, SignSpecialModel.FACTORY);
registerReader(HANGING_SIGN, SignSpecialModel.READER);
registerFactory(STANDING_SIGN, SignSpecialModel.FACTORY);
registerReader(STANDING_SIGN, SignSpecialModel.READER);
registerFactory(PLAYER_HEAD, PlayerHeadSpecialModel.FACTORY);
registerReader(PLAYER_HEAD, PlayerHeadSpecialModel.READER);
registerFactory(CHEST, ChestSpecialModel.FACTORY);
registerReader(CHEST, ChestSpecialModel.READER);
registerFactory(BANNER, BannerSpecialModel.FACTORY);
registerReader(BANNER, BannerSpecialModel.READER);
registerFactory(BED, BedSpecialModel.FACTORY);
registerReader(BED, BedSpecialModel.READER);
registerFactory(HEAD, HeadSpecialModel.FACTORY);
registerReader(HEAD, HeadSpecialModel.READER);
registerFactory(SHULKER_BOX, ShulkerBoxSpecialModel.FACTORY);
registerReader(SHULKER_BOX, ShulkerBoxSpecialModel.READER);
}
public static void register(Key key, SpecialModelFactory factory) {
public static void registerFactory(Key key, SpecialModelFactory factory) {
Holder.Reference<SpecialModelFactory> holder = ((WritableRegistry<SpecialModelFactory>) BuiltInRegistries.SPECIAL_MODEL_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.SPECIAL_MODEL_FACTORY.location(), key));
holder.bindValue(factory);
}
public static void registerReader(Key key, SpecialModelReader factory) {
Holder.Reference<SpecialModelReader> holder = ((WritableRegistry<SpecialModelReader>) BuiltInRegistries.SPECIAL_MODEL_READER)
.registerForHolder(new ResourceKey<>(Registries.SPECIAL_MODEL_READER.location(), key));
holder.bindValue(factory);
}
public static SpecialModel fromMap(Map<String, Object> map) {
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.item.model.special.missing_type");
Key key = Key.withDefaultNamespace(type, "minecraft");
@@ -52,4 +74,14 @@ public class SpecialModels {
}
return factory.create(map);
}
public static SpecialModel fromJson(JsonObject json) {
String type = json.get("type").getAsString();
Key key = Key.withDefaultNamespace(type, "minecraft");
SpecialModelReader reader = BuiltInRegistries.SPECIAL_MODEL_READER.getValue(key);
if (reader == null) {
throw new IllegalArgumentException("Invalid special model type: " + key);
}
return reader.read(json);
}
}

View File

@@ -10,6 +10,7 @@ import java.util.Map;
public class ConstantTint implements Tint {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Either<Integer, List<Float>> value;
public ConstantTint(Either<Integer, List<Float>> value) {
@@ -30,11 +31,17 @@ public class ConstantTint implements Tint {
}
public static class Factory implements TintFactory {
@Override
public Tint create(Map<String, Object> arguments) {
Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("value"), "warning.config.item.model.tint.constant.missing_value");
Object value = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "value", "default"), "warning.config.item.model.tint.constant.missing_value");
return new ConstantTint(parseTintValue(value));
}
}
public static class Reader implements TintReader {
@Override
public Tint read(JsonObject json) {
return new ConstantTint(parseTintValue(json.get("value")));
}
}
}

View File

@@ -10,6 +10,7 @@ import java.util.Map;
public class CustomModelDataTint implements Tint {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final Either<Integer, List<Float>> value;
private final int index;
@@ -28,18 +29,27 @@ public class CustomModelDataTint implements Tint {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
if (index != 0)
json.addProperty("index", index);
applyAnyTint(json, value, "default");
json.addProperty("index", this.index);
applyAnyTint(json, this.value, "default");
return json;
}
public static class Factory implements TintFactory {
@Override
public Tint create(Map<String, Object> arguments) {
Object value = arguments.getOrDefault("default", 0);
Object value = arguments.containsKey("default") ? arguments.getOrDefault("default", 0) : arguments.getOrDefault("value", 0);
int index = ResourceConfigUtils.getAsInt(arguments.getOrDefault("index", 0), "index");
return new CustomModelDataTint(parseTintValue(value), index);
}
}
public static class Reader implements TintReader {
@Override
public Tint read(JsonObject json) {
return new CustomModelDataTint(
parseTintValue(json.get("default")),
json.has("index") ? json.get("index").getAsInt() : 0
);
}
}
}

View File

@@ -9,6 +9,7 @@ import java.util.Map;
public class GrassTint implements Tint {
public static final Factory FACTORY = new Factory();
public static final Reader READER = new Reader();
private final float temperature;
private final float downfall;
@@ -32,7 +33,6 @@ public class GrassTint implements Tint {
}
public static class Factory implements TintFactory {
@Override
public Tint create(Map<String, Object> arguments) {
float temperature = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("temperature", 0), "temperature");
@@ -46,4 +46,13 @@ public class GrassTint implements Tint {
return new GrassTint(temperature, downfall);
}
}
public static class Reader implements TintReader {
@Override
public Tint read(JsonObject json) {
float temperature = json.has("temperature") ? json.get("temperature").getAsFloat() : 0;
float downfall = json.has("downfall") ? json.get("downfall").getAsFloat() : 0;
return new GrassTint(temperature, downfall);
}
}
}

View File

@@ -3,17 +3,19 @@ package net.momirealms.craftengine.core.pack.model.tint;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.util.Key;
import org.incendo.cloud.type.Either;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
public class SimpleDefaultTint implements Tint {
public static final Factory FACTORY = new Factory();
private final Either<Integer, List<Float>> value;
public static final Reader READER = new Reader();
private final Either<Integer, List<Float>> defaultValue;
private final Key type;
public SimpleDefaultTint(Either<Integer, List<Float>> value, Key type) {
this.value = value;
public SimpleDefaultTint(Key type, @Nullable Either<Integer, List<Float>> defaultValue) {
this.defaultValue = defaultValue;
this.type = type;
}
@@ -26,17 +28,23 @@ public class SimpleDefaultTint implements Tint {
public JsonObject get() {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
applyAnyTint(json, value, "default");
applyAnyTint(json, this.defaultValue, "default");
return json;
}
public static class Factory implements TintFactory {
@Override
public Tint create(Map<String, Object> arguments) {
Object value = arguments.getOrDefault("default", 0);
Object value = arguments.containsKey("default") ? arguments.getOrDefault("default", 0) : arguments.getOrDefault("value", 0);
Key type = Key.of(arguments.get("type").toString());
return new SimpleDefaultTint(parseTintValue(value), type);
return new SimpleDefaultTint(type, parseTintValue(value));
}
}
public static class Reader implements TintReader {
@Override
public Tint read(JsonObject json) {
return new SimpleDefaultTint(Key.of(json.get("type").getAsString()), parseTintValue(json.get("default")));
}
}
}

View File

@@ -13,6 +13,7 @@ public interface Tint extends Supplier<JsonObject> {
Key type();
default void applyAnyTint(JsonObject json, Either<Integer, List<Float>> value, String key) {
if (value == null) return;
if (value.primary().isPresent()) {
json.addProperty(key, value.primary().get());
} else {

View File

@@ -0,0 +1,30 @@
package net.momirealms.craftengine.core.pack.model.tint;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.incendo.cloud.type.Either;
import java.util.ArrayList;
import java.util.List;
public interface TintReader {
Tint read(JsonObject json);
default Either<Integer, List<Float>> parseTintValue(JsonElement element) {
if (element instanceof JsonPrimitive jsonPrimitive) {
return Either.ofPrimary(jsonPrimitive.getAsInt());
} else if (element instanceof JsonArray array) {
List<Float> result = new ArrayList<>();
for (JsonElement jsonElement : array) {
result.add(jsonElement.getAsFloat());
}
return Either.ofFallback(result);
} else if (element instanceof JsonObject object) {
throw new IllegalArgumentException("Can't parse tint value: " + object);
}
return null;
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.pack.model.tint;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -22,22 +23,36 @@ public class Tints {
public static final Key TEAM = Key.of("minecraft:team");
static {
register(CONSTANT, ConstantTint.FACTORY);
register(CUSTOM_MODEL_DATA, CustomModelDataTint.FACTORY);
register(GRASS, GrassTint.FACTORY);
register(DYE, SimpleDefaultTint.FACTORY);
register(FIREWORK, SimpleDefaultTint.FACTORY);
register(MAP_COLOR, SimpleDefaultTint.FACTORY);
register(POTION, SimpleDefaultTint.FACTORY);
register(TEAM, SimpleDefaultTint.FACTORY);
registerFactory(CONSTANT, ConstantTint.FACTORY);
registerReader(CONSTANT, ConstantTint.READER);
registerFactory(CUSTOM_MODEL_DATA, CustomModelDataTint.FACTORY);
registerReader(CUSTOM_MODEL_DATA, CustomModelDataTint.READER);
registerFactory(GRASS, GrassTint.FACTORY);
registerReader(GRASS, GrassTint.READER);
registerFactory(DYE, SimpleDefaultTint.FACTORY);
registerReader(DYE, SimpleDefaultTint.READER);
registerFactory(FIREWORK, SimpleDefaultTint.FACTORY);
registerReader(FIREWORK, SimpleDefaultTint.READER);
registerFactory(MAP_COLOR, SimpleDefaultTint.FACTORY);
registerReader(MAP_COLOR, SimpleDefaultTint.READER);
registerFactory(POTION, SimpleDefaultTint.FACTORY);
registerReader(POTION, SimpleDefaultTint.READER);
registerFactory(TEAM, SimpleDefaultTint.FACTORY);
registerReader(TEAM, SimpleDefaultTint.READER);
}
public static void register(Key key, TintFactory factory) {
public static void registerFactory(Key key, TintFactory factory) {
Holder.Reference<TintFactory> holder = ((WritableRegistry<TintFactory>) BuiltInRegistries.TINT_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.TINT_FACTORY.location(), key));
holder.bindValue(factory);
}
public static void registerReader(Key key, TintReader reader) {
Holder.Reference<TintReader> holder = ((WritableRegistry<TintReader>) BuiltInRegistries.TINT_READER)
.registerForHolder(new ResourceKey<>(Registries.TINT_READER.location(), key));
holder.bindValue(reader);
}
public static Tint fromMap(Map<String, Object> map) {
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.item.model.tint.missing_type");
Key key = Key.withDefaultNamespace(type, "minecraft");
@@ -47,4 +62,14 @@ public class Tints {
}
return factory.create(map);
}
public static Tint fromJson(JsonObject json) {
String type = json.get("type").getAsString();
Key key = Key.withDefaultNamespace(type, "minecraft");
TintReader reader = BuiltInRegistries.TINT_READER.getValue(key);
if (reader == null) {
throw new IllegalArgumentException("Invalid tint type: " + type);
}
return reader.read(json);
}
}

View File

@@ -0,0 +1,139 @@
package net.momirealms.craftengine.core.pack.revision;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MinecraftVersions;
import java.util.Objects;
public interface Revision {
int minPackVersion();
int maxPackVersion();
String versionString();
boolean matches(MinecraftVersion min, MinecraftVersion max);
MinecraftVersion minVersion();
MinecraftVersion maxVersion();
static Revision since(MinecraftVersion minecraftVersion) {
return new Since(minecraftVersion);
}
static Revision fromTo(MinecraftVersion from, MinecraftVersion to) {
return new FromTo(from, to);
}
class Since implements Revision {
private final MinecraftVersion minVersion;
private String versionString;
public Since(MinecraftVersion minVersion) {
this.minVersion = minVersion;
}
@Override
public MinecraftVersion maxVersion() {
return MinecraftVersions.FUTURE;
}
@Override
public MinecraftVersion minVersion() {
return this.minVersion;
}
@Override
public String versionString() {
if (this.versionString == null) {
this.versionString = this.minVersion.version().replace(".", "_");
}
return this.versionString;
}
@Override
public boolean matches(MinecraftVersion min, MinecraftVersion max) {
return this.minVersion.isAtOrBelow(max);
}
@Override
public int maxPackVersion() {
return MinecraftVersions.FUTURE.packFormat();
}
@Override
public int minPackVersion() {
return this.minVersion.packFormat();
}
@Override
public final boolean equals(Object object) {
if (!(object instanceof Since since)) return false;
return this.minVersion.equals(since.minVersion);
}
@Override
public int hashCode() {
return this.minVersion.hashCode();
}
}
class FromTo implements Revision {
private final MinecraftVersion minVersion;
private final MinecraftVersion maxVersion;
private String versionString;
public FromTo(MinecraftVersion minVersion, MinecraftVersion maxVersion) {
this.minVersion = minVersion;
this.maxVersion = maxVersion;
}
@Override
public MinecraftVersion maxVersion() {
return this.maxVersion;
}
@Override
public MinecraftVersion minVersion() {
return this.minVersion;
}
@Override
public boolean matches(MinecraftVersion min, MinecraftVersion max) {
return !min.isAbove(this.maxVersion) || !max.isBelow(this.minVersion);
}
@Override
public int minPackVersion() {
return this.minVersion.packFormat();
}
@Override
public int maxPackVersion() {
return this.maxVersion.packFormat();
}
@Override
public String versionString() {
if (this.versionString == null) {
this.versionString = this.minVersion.version().replace(".", "_") + "-" + this.maxVersion.version().replace(".", "_");
}
return this.versionString;
}
@Override
public final boolean equals(Object object) {
if (!(object instanceof FromTo fromTo)) return false;
return Objects.equals(minVersion, fromTo.minVersion) && Objects.equals(maxVersion, fromTo.maxVersion);
}
@Override
public int hashCode() {
int result = Objects.hashCode(minVersion);
result = 31 * result + Objects.hashCode(maxVersion);
return result;
}
}
}

View File

@@ -0,0 +1,9 @@
package net.momirealms.craftengine.core.pack.revision;
import net.momirealms.craftengine.core.util.MinecraftVersions;
public final class Revisions {
private Revisions() {}
public static final Revision SINCE_1_21_6 = Revision.since(MinecraftVersions.V1_21_6);
}

View File

@@ -21,6 +21,7 @@ import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
import net.momirealms.craftengine.core.plugin.logger.filter.DisconnectLogFilter;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MinecraftVersion;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.world.InjectionTarget;
import net.momirealms.craftengine.core.world.chunk.storage.CompressionMethod;
@@ -80,8 +81,9 @@ public class Config {
protected List<String> resource_pack$protection$obfuscation$resource_location$bypass_sounds;
protected List<String> resource_pack$protection$obfuscation$resource_location$bypass_equipments;
protected float resource_pack$supported_version$min;
protected float resource_pack$supported_version$max;
protected MinecraftVersion resource_pack$supported_version$min;
protected MinecraftVersion resource_pack$supported_version$max;
protected String resource_pack$overlay_format;
protected boolean resource_pack$delivery$kick_if_declined;
protected boolean resource_pack$delivery$send_on_join;
@@ -264,6 +266,10 @@ public class Config {
resource_pack$protection$obfuscation$resource_location$bypass_equipments = config.getStringList("resource-pack.protection.obfuscation.resource-location.bypass-equipments");
resource_pack$validate$enable = config.getBoolean("resource-pack.validate.enable", true);
resource_pack$exclude_core_shaders = config.getBoolean("resource-pack.exclude-core-shaders", false);
resource_pack$overlay_format = config.getString("resource-pack.overlay-format", "overlay_{version}");
if (!resource_pack$overlay_format.contains("{version}")) {
TranslationManager.instance().log("warning.config.resource_pack.invalid_overlay_format", resource_pack$overlay_format);
}
try {
resource_pack$duplicated_files_handler = config.getMapList("resource-pack.duplicated-files-handler").stream().map(it -> {
@@ -363,15 +369,11 @@ public class Config {
firstTime = false;
}
private static float getVersion(String version) {
private static MinecraftVersion getVersion(String version) {
if (version.equalsIgnoreCase("LATEST")) {
version = PluginProperties.getValue("latest-version");
return new MinecraftVersion(PluginProperties.getValue("latest-version"));
}
String[] split = version.split("\\.", 2);
if (split.length != 2) {
throw new IllegalArgumentException("Invalid version: " + version);
}
return Float.parseFloat(split[1]);
return MinecraftVersion.parse(version);
}
public static String configVersion() {
@@ -422,11 +424,11 @@ public class Config {
return instance.light_system$enable;
}
public static float packMinVersion() {
public static MinecraftVersion packMinVersion() {
return instance.resource_pack$supported_version$min;
}
public static float packMaxVersion() {
public static MinecraftVersion packMaxVersion() {
return instance.resource_pack$supported_version$max;
}
@@ -742,6 +744,10 @@ public class Config {
return instance.resource_pack$exclude_core_shaders;
}
public static String createOverlayFolderName(String version) {
return instance.resource_pack$overlay_format.replace("{version}", version);
}
public YamlDocument loadOrCreateYamlData(String fileName) {
Path path = this.plugin.dataFolderPath().resolve(fileName);
if (!Files.exists(path)) {

View File

@@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.SNBTReader;
import java.util.ArrayList;
import java.util.List;
@@ -76,7 +77,8 @@ public interface TemplateManager extends Manageable {
this.placeholder = placeholderContent.substring(0, separatorIndex);
String defaultValueString = placeholderContent.substring(separatorIndex + 2);
try {
this.defaultValue = CraftEngine.instance().platform().snbtToJava(defaultValueString);
// TODO 改进报错检测
this.defaultValue = new SNBTReader(defaultValueString).deserializeAsJava();
} catch (LocalizedResourceConfigException e) {
e.appendTailArgument(this.placeholder);
throw e;

View File

@@ -129,7 +129,9 @@ public interface GuiElement {
@Override
public Item<?> item() {
return gui().itemAt(this.index).item();
ItemWithAction item = gui().itemAt(this.index);
if (item == null) return null;
return item.item();
}
@Override

View File

@@ -15,11 +15,17 @@ import net.momirealms.craftengine.core.pack.conflict.PathContext;
import net.momirealms.craftengine.core.pack.conflict.resolution.ResolutionFactory;
import net.momirealms.craftengine.core.pack.host.ResourcePackHostFactory;
import net.momirealms.craftengine.core.pack.model.ItemModelFactory;
import net.momirealms.craftengine.core.pack.model.ItemModelReader;
import net.momirealms.craftengine.core.pack.model.condition.ConditionPropertyFactory;
import net.momirealms.craftengine.core.pack.model.condition.ConditionPropertyReader;
import net.momirealms.craftengine.core.pack.model.rangedisptach.RangeDispatchPropertyFactory;
import net.momirealms.craftengine.core.pack.model.rangedisptach.RangeDispatchPropertyReader;
import net.momirealms.craftengine.core.pack.model.select.SelectPropertyFactory;
import net.momirealms.craftengine.core.pack.model.select.SelectPropertyReader;
import net.momirealms.craftengine.core.pack.model.special.SpecialModelFactory;
import net.momirealms.craftengine.core.pack.model.special.SpecialModelReader;
import net.momirealms.craftengine.core.pack.model.tint.TintFactory;
import net.momirealms.craftengine.core.pack.model.tint.TintReader;
import net.momirealms.craftengine.core.plugin.config.template.TemplateArgumentFactory;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
@@ -41,11 +47,17 @@ public class BuiltInRegistries {
public static final Registry<NumberProviderFactory> NUMBER_PROVIDER_FACTORY = createRegistry(Registries.NUMBER_PROVIDER_FACTORY);
public static final Registry<TemplateArgumentFactory> TEMPLATE_ARGUMENT_FACTORY = createRegistry(Registries.TEMPLATE_ARGUMENT_FACTORY);
public static final Registry<ItemModelFactory> ITEM_MODEL_FACTORY = createRegistry(Registries.ITEM_MODEL_FACTORY);
public static final Registry<ItemModelReader> ITEM_MODEL_READER = createRegistry(Registries.ITEM_MODEL_READER);
public static final Registry<TintFactory> TINT_FACTORY = createRegistry(Registries.TINT_FACTORY);
public static final Registry<TintReader> TINT_READER = createRegistry(Registries.TINT_READER);
public static final Registry<SpecialModelFactory> SPECIAL_MODEL_FACTORY = createRegistry(Registries.SPECIAL_MODEL_FACTORY);
public static final Registry<SpecialModelReader> SPECIAL_MODEL_READER = createRegistry(Registries.SPECIAL_MODEL_READER);
public static final Registry<RangeDispatchPropertyFactory> RANGE_DISPATCH_PROPERTY_FACTORY = createRegistry(Registries.RANGE_DISPATCH_PROPERTY_FACTORY);
public static final Registry<RangeDispatchPropertyReader> RANGE_DISPATCH_PROPERTY_READER = createRegistry(Registries.RANGE_DISPATCH_PROPERTY_READER);
public static final Registry<ConditionPropertyFactory> CONDITION_PROPERTY_FACTORY = createRegistry(Registries.CONDITION_PROPERTY_FACTORY);
public static final Registry<ConditionPropertyReader> CONDITION_PROPERTY_READER = createRegistry(Registries.CONDITION_PROPERTY_READER);
public static final Registry<SelectPropertyFactory> SELECT_PROPERTY_FACTORY = createRegistry(Registries.SELECT_PROPERTY_FACTORY);
public static final Registry<SelectPropertyReader> SELECT_PROPERTY_READER = createRegistry(Registries.SELECT_PROPERTY_READER);
public static final Registry<RecipeFactory<?>> RECIPE_FACTORY = createRegistry(Registries.RECIPE_FACTORY);
public static final Registry<ApplyBonusCountFunction.FormulaFactory> FORMULA_FACTORY = createRegistry(Registries.FORMULA_FACTORY);
public static final Registry<ConditionFactory<PathContext>> PATH_MATCHER_FACTORY = createRegistry(Registries.PATH_MATCHER_FACTORY);

View File

@@ -15,11 +15,17 @@ import net.momirealms.craftengine.core.pack.conflict.PathContext;
import net.momirealms.craftengine.core.pack.conflict.resolution.ResolutionFactory;
import net.momirealms.craftengine.core.pack.host.ResourcePackHostFactory;
import net.momirealms.craftengine.core.pack.model.ItemModelFactory;
import net.momirealms.craftengine.core.pack.model.ItemModelReader;
import net.momirealms.craftengine.core.pack.model.condition.ConditionPropertyFactory;
import net.momirealms.craftengine.core.pack.model.condition.ConditionPropertyReader;
import net.momirealms.craftengine.core.pack.model.rangedisptach.RangeDispatchPropertyFactory;
import net.momirealms.craftengine.core.pack.model.rangedisptach.RangeDispatchPropertyReader;
import net.momirealms.craftengine.core.pack.model.select.SelectPropertyFactory;
import net.momirealms.craftengine.core.pack.model.select.SelectPropertyReader;
import net.momirealms.craftengine.core.pack.model.special.SpecialModelFactory;
import net.momirealms.craftengine.core.pack.model.special.SpecialModelReader;
import net.momirealms.craftengine.core.pack.model.tint.TintFactory;
import net.momirealms.craftengine.core.pack.model.tint.TintReader;
import net.momirealms.craftengine.core.plugin.config.template.TemplateArgumentFactory;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
@@ -42,11 +48,17 @@ public class Registries {
public static final ResourceKey<Registry<NumberProviderFactory>> NUMBER_PROVIDER_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("number_provider_factory"));
public static final ResourceKey<Registry<TemplateArgumentFactory>> TEMPLATE_ARGUMENT_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("template_argument_factory"));
public static final ResourceKey<Registry<ItemModelFactory>> ITEM_MODEL_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("item_model_factory"));
public static final ResourceKey<Registry<ItemModelReader>> ITEM_MODEL_READER = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("item_model_reader"));
public static final ResourceKey<Registry<TintFactory>> TINT_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("tint_factory"));
public static final ResourceKey<Registry<TintReader>> TINT_READER = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("tint_reader"));
public static final ResourceKey<Registry<SpecialModelFactory>> SPECIAL_MODEL_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("special_model_factory"));
public static final ResourceKey<Registry<SpecialModelReader>> SPECIAL_MODEL_READER = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("special_model_reader"));
public static final ResourceKey<Registry<RangeDispatchPropertyFactory>> RANGE_DISPATCH_PROPERTY_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("range_dispatch_property_factory"));
public static final ResourceKey<Registry<RangeDispatchPropertyReader>> RANGE_DISPATCH_PROPERTY_READER = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("range_dispatch_property_reader"));
public static final ResourceKey<Registry<ConditionPropertyFactory>> CONDITION_PROPERTY_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("condition_property_factory"));
public static final ResourceKey<Registry<ConditionPropertyReader>> CONDITION_PROPERTY_READER = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("condition_property_reader"));
public static final ResourceKey<Registry<SelectPropertyFactory>> SELECT_PROPERTY_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("select_property_factory"));
public static final ResourceKey<Registry<SelectPropertyReader>> SELECT_PROPERTY_READER = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("select_property_reader"));
public static final ResourceKey<Registry<RecipeFactory<?>>> RECIPE_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_factory"));
public static final ResourceKey<Registry<ApplyBonusCountFunction.FormulaFactory>> FORMULA_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("formula_factory"));
public static final ResourceKey<Registry<ConditionFactory<PathContext>>> PATH_MATCHER_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory"));

View File

@@ -4,9 +4,9 @@ public class DefaultStringReader implements StringReader {
private static final char SYNTAX_ESCAPE = '\\';
private static final char SYNTAX_DOUBLE_QUOTE = '"';
private static final char SYNTAX_SINGLE_QUOTE = '\'';
private final String string;
private int cursor;
private int marker;
protected final String string;
protected int cursor;
protected int marker;
public DefaultStringReader(DefaultStringReader other) {
this.string = other.string;
@@ -112,10 +112,24 @@ public class DefaultStringReader implements StringReader {
this.cursor += count;
}
@Override
public char charAt(int index) {
return this.string.charAt(index);
}
@Override
public String substring(int start, int end) {
return this.string.substring(start, end);
}
public static boolean isAllowedNumber(char c) {
return c >= '0' && c <= '9' || c == '.' || c == '-';
}
public static boolean isNumber(char c) {
return c >= '0' && c <= '9';
}
public static boolean isQuotedStringStart(char c) {
return c == SYNTAX_DOUBLE_QUOTE || c == SYNTAX_SINGLE_QUOTE;
}

View File

@@ -0,0 +1,83 @@
package net.momirealms.craftengine.core.util;
import java.util.HashMap;
import java.util.Map;
public final class MinecraftVersion implements Comparable<MinecraftVersion> {
public static final Map<Integer, Integer> PACK_FORMATS = new HashMap<>();
static {
PACK_FORMATS.put(1_20_00, 15);
PACK_FORMATS.put(1_20_01, 15);
PACK_FORMATS.put(1_20_02, 18);
PACK_FORMATS.put(1_20_03, 22);
PACK_FORMATS.put(1_20_04, 22);
PACK_FORMATS.put(1_20_05, 32);
PACK_FORMATS.put(1_20_06, 32);
PACK_FORMATS.put(1_21_00, 34);
PACK_FORMATS.put(1_21_01, 34);
PACK_FORMATS.put(1_21_02, 42);
PACK_FORMATS.put(1_21_03, 42);
PACK_FORMATS.put(1_21_04, 46);
PACK_FORMATS.put(1_21_05, 55);
PACK_FORMATS.put(1_21_06, 63);
PACK_FORMATS.put(1_99_99, 1000);
}
private final int version;
private final String versionString;
private final int packFormat;
public static MinecraftVersion parse(final String version) {
return new MinecraftVersion(version);
}
public String version() {
return versionString;
}
public int packFormat() {
return packFormat;
}
public MinecraftVersion(String version) {
this.version = VersionHelper.parseVersionToInteger(version);
this.versionString = version;
this.packFormat = PACK_FORMATS.get(this.version);
}
public boolean isAtOrAbove(MinecraftVersion other) {
return version >= other.version;
}
public boolean isAtOrBelow(MinecraftVersion other) {
return version <= other.version;
}
public boolean isAt(MinecraftVersion other) {
return version == other.version;
}
public boolean isBelow(MinecraftVersion other) {
return version < other.version;
}
public boolean isAbove(MinecraftVersion other) {
return version > other.version;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof MinecraftVersion that)) return false;
return version == that.version;
}
@Override
public int hashCode() {
return version;
}
@Override
public int compareTo(MinecraftVersion other) {
return Integer.compare(this.version, other.version);
}
}

View File

@@ -0,0 +1,21 @@
package net.momirealms.craftengine.core.util;
public final class MinecraftVersions {
private MinecraftVersions() {}
public static final MinecraftVersion V1_20 = new MinecraftVersion("1.20");
public static final MinecraftVersion V1_20_1 = new MinecraftVersion("1.20.1");
public static final MinecraftVersion V1_20_2 = new MinecraftVersion("1.20.2");
public static final MinecraftVersion V1_20_3 = new MinecraftVersion("1.20.3");
public static final MinecraftVersion V1_20_4 = new MinecraftVersion("1.20.4");
public static final MinecraftVersion V1_20_5 = new MinecraftVersion("1.20.5");
public static final MinecraftVersion V1_20_6 = new MinecraftVersion("1.20.6");
public static final MinecraftVersion V1_21 = new MinecraftVersion("1.21");
public static final MinecraftVersion V1_21_1 = new MinecraftVersion("1.21.1");
public static final MinecraftVersion V1_21_2 = new MinecraftVersion("1.21.2");
public static final MinecraftVersion V1_21_3 = new MinecraftVersion("1.21.3");
public static final MinecraftVersion V1_21_4 = new MinecraftVersion("1.21.4");
public static final MinecraftVersion V1_21_5 = new MinecraftVersion("1.21.5");
public static final MinecraftVersion V1_21_6 = new MinecraftVersion("1.21.6");
public static final MinecraftVersion FUTURE = new MinecraftVersion("1.99.99");
}

View File

@@ -1,336 +0,0 @@
package net.momirealms.craftengine.core.util;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class SNBTDeserializer {
private static final char COMPOUND_START = '{';
private static final char COMPOUND_END = '}';
private static final char LIST_START = '[';
private static final char LIST_END = ']';
private static final char STRING_DELIMITER = '"';
private static final char KEY_VALUE_SEPARATOR = ':';
private static final char ELEMENT_SEPARATOR = ',';
private static final char ESCAPE_CHAR = '\\';
// 数字类型后缀
private static final char BYTE_SUFFIX = 'b';
private static final char SHORT_SUFFIX = 's';
private static final char LONG_SUFFIX = 'l';
private static final char FLOAT_SUFFIX = 'f';
private static final char DOUBLE_SUFFIX = 'd';
private static final char BOOLEAN_SUFFIX = 'B';
// 布尔值常量
private static final String TRUE_LITERAL = "true";
private static final String FALSE_LITERAL = "false";
private static final int TRUE_LENGTH = 4;
private static final int FALSE_LENGTH = 5;
// 使用 char[] 处理获得更高的性能
private final char[] sourceContent;
private final int length;
private int position = 0;
private SNBTDeserializer(String content) {
this.sourceContent = content.toCharArray();
this.length = sourceContent.length;
}
// 入口API
public static Object parse(String input) throws IllegalArgumentException {
SNBTDeserializer parser = new SNBTDeserializer(input);
Object result = parser.parseValue();
parser.skipWhitespace();
if (parser.position != parser.length) {
throw new IllegalArgumentException("Extra content at end: " +
new String(parser.sourceContent, parser.position,
parser.length - parser.position));
}
return result;
}
// 开始解析, 步进字符.
private Object parseValue() {
skipWhitespace();
return switch (peekCurrentChar()) {
case COMPOUND_START -> parseCompound();
case LIST_START -> parseList();
case STRING_DELIMITER -> parseString();
default -> parsePrimitive();
};
}
// 解析包小肠 {}
private Map<String, Object> parseCompound() {
position++; // 跳过 '{'
skipWhitespace();
Map<String, Object> compoundMap = new LinkedHashMap<>(16); // 避免一次扩容, 应该有一定的性能提升
if (position < length && sourceContent[position] != COMPOUND_END) {
do {
String key = parseKey();
if (position >= length || sourceContent[position] != KEY_VALUE_SEPARATOR) {
throw new IllegalArgumentException("Expected ':' at position " + position);
}
position++; // 跳过 ':'
Object value = parseValue();
compoundMap.put(key, value);
skipWhitespace();
} while (position < length && sourceContent[position] == ELEMENT_SEPARATOR && ++position > 0);
}
if (position >= length || sourceContent[position] != COMPOUND_END) {
throw new IllegalArgumentException("Expected '}' at position " + position);
}
position++; // 跳过 '}'
return compoundMap;
}
// 解析列表值 [1, 2, 3]
private List<Object> parseList() {
position++; // 跳过 '['
skipWhitespace();
List<Object> elementList = new ArrayList<>();
if (position < length && sourceContent[position] != LIST_END) {
do {
elementList.add(parseValue());
skipWhitespace();
} while (position < length && sourceContent[position] == ELEMENT_SEPARATOR && ++position > 0);
}
if (position >= length || sourceContent[position] != LIST_END) {
throw new IllegalArgumentException("Expected ']' at position " + position);
}
position++; // 跳过 ']'
return elementList;
}
// 解析字符串
private String parseString() {
position++; // 跳过开始的引号
int start = position;
// 扫一次字符串, 如果没有发现转义就直接返回, 发现了就再走转义解析.
// 这样可以避免创建一次 StringBuilder.
while (position < length) {
char c = sourceContent[position];
if (c == STRING_DELIMITER) {
String result = new String(sourceContent, start, position - start);
position++; // 跳过结束引号
return result; // 没有转义直接返回字符串.
}
// 如果发现转义字符,
else if (c == ESCAPE_CHAR) {
return parseStringWithEscape(start);
}
position++;
}
// 没有扫描到结束引号
throw new IllegalArgumentException("Unterminated string at " + start);
}
// 处理含转义的字符串
private String parseStringWithEscape(int start) {
StringBuilder sb = new StringBuilder(position - start + 16);
sb.append(sourceContent, start, position - start);
while (position < length) {
char c = sourceContent[position++];
if (c == ESCAPE_CHAR && position < length) {
sb.append(getEscapedChar(sourceContent[position++]));
} else if (c == STRING_DELIMITER) { // 字符
return sb.toString();
} else {
sb.append(c);
}
}
// 没有扫描到结束引号
throw new IllegalArgumentException("Unterminated string at " + start);
}
// 解析Key值
private String parseKey() {
skipWhitespace();
// 如果有双引号就委托给string解析处理.
if (position < length && sourceContent[position] == STRING_DELIMITER) {
return parseString();
}
int start = position;
while (position < length) {
char c = sourceContent[position];
if (Character.isJavaIdentifierPart(c)) {
position++;
} else {
break;
}
}
skipWhitespace();
return new String(sourceContent, start, position - start);
}
// 解析原生值
private Object parsePrimitive() {
skipWhitespace();
int tokenStart = position;
// 先解析获取值的长度
while (position < length) {
char c = sourceContent[position];
if (c <= ' ' || c == ',' || c == ']' || c == '}') break;
position++;
}
int tokenLength = position - tokenStart;
if (tokenLength == 0) {
throw new IllegalArgumentException("Empty value at position " + tokenStart);
}
// 布尔值快速检查
if (tokenLength == TRUE_LENGTH && matchesAt(tokenStart, TRUE_LITERAL)) {
return Boolean.TRUE;
}
if (tokenLength == FALSE_LENGTH && matchesAt(tokenStart, FALSE_LITERAL)) {
return Boolean.FALSE;
}
// 带后缀的值处理
try {
char lastChar = sourceContent[tokenStart + tokenLength - 1];
if (tokenLength > 1 && isTypeSuffix(lastChar)) {
return switch (lastChar) {
case BYTE_SUFFIX -> parseByte(tokenStart, tokenLength - 1);
case SHORT_SUFFIX -> parseShort(tokenStart, tokenLength - 1);
case LONG_SUFFIX -> parseLong(tokenStart, tokenLength - 1);
case FLOAT_SUFFIX -> Float.parseFloat(new String(sourceContent, tokenStart, tokenLength - 1));
case DOUBLE_SUFFIX -> Double.parseDouble(new String(sourceContent, tokenStart, tokenLength - 1));
case BOOLEAN_SUFFIX -> parseBoolean(new String(sourceContent, tokenStart, tokenLength - 1));
default -> throw new IllegalArgumentException("Invalid suffixed value " + new String(sourceContent, tokenStart, tokenLength - 1));
};
}
// 没有后缀就默认为 double 喵
return Double.parseDouble(new String(sourceContent, tokenStart, tokenLength));
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid number value at position " + tokenStart, e);
}
}
// 工具函数: 快速检查布尔值字符串匹配, 忽略大小写.
private boolean matchesAt(int start, String target) {
for (int i = 0; i < target.length(); i++) {
char c1 = sourceContent[start + i];
char c2 = target.charAt(i);
if (c1 != c2 && c1 != (c2 ^ 32)) return false; // 忽略大小写比较
}
return true;
}
// 工具函数: 合法后缀检查
private boolean isTypeSuffix(char c) {
return c == BYTE_SUFFIX || c == SHORT_SUFFIX || c == LONG_SUFFIX ||
c == FLOAT_SUFFIX || c == DOUBLE_SUFFIX || c == BOOLEAN_SUFFIX;
}
// 手动解析值
private byte parseByte(int start, int length) {
int value = parseInteger(start, length);
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE)
throw new IllegalArgumentException("Byte value out of range");
return (byte) value;
}
private short parseShort(int start, int length) {
int value = parseInteger(start, length);
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE)
throw new NumberFormatException("Short value out of range");
return (short) value;
}
private Boolean parseBoolean(String content) {
if ("1".equals(content)) return Boolean.TRUE;
if ("0".equals(content)) return Boolean.FALSE;
throw new NumberFormatException("Invalid boolean value");
}
private int parseInteger(int start, int length) {
int result = 0;
boolean negative = false;
int i = 0;
if (sourceContent[start] == '-') {
negative = true;
i = 1;
}
for (; i < length; i++) {
char c = sourceContent[start + i];
if (c < '0' || c > '9') throw new NumberFormatException("Invalid integer");
result = result * 10 + (c - '0');
}
return negative ? -result : result;
}
private long parseLong(int start, int length) {
long result = 0;
boolean negative = false;
int i = 0;
if (sourceContent[start] == '-') {
negative = true;
i = 1;
}
for (; i < length; i++) {
char c = sourceContent[start + i];
if (c < '0' || c > '9') throw new NumberFormatException("Invalid long");
result = result * 10 + (c - '0');
}
return negative ? -result : result;
}
// 转义字符处理
private char getEscapedChar(char escapedChar) {
return switch (escapedChar) {
case STRING_DELIMITER -> '"';
case ESCAPE_CHAR -> '\\';
case COMPOUND_START -> '{';
case COMPOUND_END -> '}';
case LIST_START -> '[';
case LIST_END -> ']';
case KEY_VALUE_SEPARATOR -> ':';
case ELEMENT_SEPARATOR -> ',';
default -> escapedChar;
};
}
// 获取当前字符
private char peekCurrentChar() {
if (position >= length) throw new IllegalArgumentException("Unexpected end of input at position " + position);
return sourceContent[position];
}
// 跳过空格
private void skipWhitespace() {
while (position < length) {
char c = sourceContent[position];
if (c > ' ') { break; } // 大于空格的字符都不是空白字符
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
position++;
} else {
break;
}
}
}
}

View File

@@ -0,0 +1,217 @@
package net.momirealms.craftengine.core.util;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public final class SNBTReader extends DefaultStringReader {
private static final char COMPOUND_START = '{';
private static final char COMPOUND_END = '}';
private static final char LIST_START = '[';
private static final char LIST_END = ']';
private static final char STRING_DELIMITER = '"';
private static final char SINGLE_QUOTES = '\'';
private static final char DOUBLE_QUOTES = '"';
private static final char KEY_VALUE_SEPARATOR = ':';
private static final char ELEMENT_SEPARATOR = ',';
// 数字类型后缀
private static final char BYTE_SUFFIX = 'b';
private static final char SHORT_SUFFIX = 's';
private static final char LONG_SUFFIX = 'l';
private static final char FLOAT_SUFFIX = 'f';
private static final char DOUBLE_SUFFIX = 'd';
public SNBTReader(String content) {
super(content);
}
public Object deserializeAsJava() {
Object result = this.parseValue();
this.skipWhitespace();
if (getCursor() != getTotalLength())
throw new IllegalArgumentException("Extra content at end: " + substring(getCursor(), getTotalLength()));
return result;
}
// 开始解析, 步进字符.
private Object parseValue() {
skipWhitespace();
return switch (peek()) {
case COMPOUND_START -> parseCompound();
case LIST_START -> parseList();
case DOUBLE_QUOTES -> {
skip();
yield readStringUntil(DOUBLE_QUOTES);
}
case SINGLE_QUOTES -> {
skip();
yield readStringUntil(SINGLE_QUOTES);
}
default -> parsePrimitive();
};
}
// 解析包小肠 {}
private Map<String, Object> parseCompound() {
skip(); // 跳过 '{'
skipWhitespace();
Map<String, Object> compoundMap = new LinkedHashMap<>();
if (canRead() && peek() != COMPOUND_END) {
do {
String key = parseKey();
if (!canRead() || peek() != KEY_VALUE_SEPARATOR) {
throw new IllegalArgumentException("Expected ':' at position " + getCursor());
}
skip(); // 跳过 ':'
Object value = parseValue();
compoundMap.put(key, value);
skipWhitespace();
} while (canRead() && peek() == ELEMENT_SEPARATOR && ++super.cursor > 0 /* 跳过 ',' */);
}
if (!canRead() || peek() != COMPOUND_END) {
throw new IllegalArgumentException("Expected '}' at position " + getCursor());
}
skip(); // 跳过 '}'
return compoundMap;
}
// 解析列表值 [1, 2, 3]
private List<Object> parseList() {
skip(); // 跳过 '['
skipWhitespace();
List<Object> elementList = new ArrayList<>();
if (canRead() && peek() != LIST_END) {
do {
elementList.add(parseValue());
skipWhitespace();
} while (canRead() && peek() == ELEMENT_SEPARATOR && ++super.cursor > 0 /* 跳过 ',' */);
}
if (!canRead() || peek() != LIST_END) {
throw new IllegalArgumentException("Expected ']' at position " + getCursor());
}
skip(); // 跳过 ']'
return elementList;
}
// 解析Key值
private String parseKey() {
skipWhitespace();
if (!canRead()) {
throw new IllegalArgumentException("Unterminated key at " + getCursor());
}
// 如果有双引号就委托给string解析处理.
char peek = peek();
if (peek == STRING_DELIMITER) {
skip();
return readStringUntil(STRING_DELIMITER);
} else if (peek == SINGLE_QUOTES) {
skip();
return readStringUntil(SINGLE_QUOTES);
}
int start = getCursor();
while (canRead()) {
char c = peek();
if (c == ' ') break; // 忽略 key 后面的空格, { a :1} 应当解析成 {a:1}
if (Character.isJavaIdentifierPart(c)) skip(); else break;
}
String key = substring(start, getCursor());
skipWhitespace(); // 跳过 key 后面的空格.
return key;
}
// 解析原生值
private Object parsePrimitive() {
// 先解析获取值的长度
int tokenStart = getCursor();
int lastWhitespace = 0; // 记录值末尾的空格数量,{a:炒鸡 大保健} 和 {a: 炒鸡 大保健 } 都应解析成 "炒鸡 大保健".
boolean contentHasWhitespace = false; // 记录值中有没有空格.
while (canRead()) {
char c = peek();
if (c == ',' || c == ']' || c == '}') break;
skip();
if (c == ' ') {
lastWhitespace++; // 遇到空格先增加值, 代表值尾部空格数量.
continue;
}
if (lastWhitespace > 0) {
lastWhitespace = 0; // 遇到正常字符时清空记录的尾部空格数.
contentHasWhitespace = true;
}
}
int tokenLength = getCursor() - tokenStart - lastWhitespace; // 计算值长度需要再减去尾部空格.
if (tokenLength == 0) throw new IllegalArgumentException("Empty value at position " + tokenStart);
if (contentHasWhitespace) return substring(tokenStart, tokenStart + tokenLength); // 如果值的中间有空格, 一定是字符串, 可直接返回.
// 布尔值检查
if (tokenLength == 4) {
if (matchesAt(tokenStart, "true")) return Boolean.TRUE;
} else if (tokenLength == 5) {
if (matchesAt(tokenStart, "false")) return Boolean.FALSE;
}
if (tokenLength > 1) {
// 至少有1个字符给了后缀的可能性
char lastChar = charAt(tokenStart + tokenLength - 1);
try {
switch (lastChar) {
case BYTE_SUFFIX -> {
return Byte.parseByte(substring(tokenStart, tokenStart + tokenLength - 1));
}
case SHORT_SUFFIX -> {
return Short.parseShort(substring(tokenStart, tokenStart + tokenLength - 1));
}
case LONG_SUFFIX -> {
return Long.parseLong(substring(tokenStart, tokenStart + tokenLength - 1));
}
case FLOAT_SUFFIX -> {
return Float.parseFloat(substring(tokenStart, tokenStart + tokenLength));
}
case DOUBLE_SUFFIX -> {
return Double.parseDouble(substring(tokenStart, tokenStart + tokenLength));
}
default -> {
String fullString = substring(tokenStart, tokenStart + tokenLength);
try {
double d = Double.parseDouble(fullString);
if (d % 1 != 0 || fullString.contains(".") || fullString.contains("e")) {
return d;
} else {
return (int) d;
}
} catch (NumberFormatException e) {
return fullString;
}
}
}
} catch (NumberFormatException e) {
return substring(tokenStart, tokenStart + tokenLength);
}
} else {
char onlyChar = charAt(tokenStart);
if (isNumber(onlyChar)) {
return onlyChar - '0';
} else {
return String.valueOf(onlyChar);
}
}
}
// 工具函数: 快速检查布尔值字符串匹配, 忽略大小写.
private boolean matchesAt(int start, String target) {
for (int i = 0; i < target.length(); i++) {
char c1 = charAt(start + i);
char c2 = target.charAt(i);
if (c1 != c2 && c1 != (c2 ^ 32)) return false; // 忽略大小写比较
}
return true;
}
}

View File

@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.util;
import java.util.Base64;
public class SkullUtils {
public final class SkullUtils {
private SkullUtils() {}

View File

@@ -40,6 +40,10 @@ public interface StringReader {
void skip(int count);
char charAt(int index);
String substring(int start, int end);
void skipWhitespace();
void skipWhitespaceAndComment();

View File

@@ -7,6 +7,7 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
public class VersionHelper {
public static final MinecraftVersion MINECRAFT_VERSION;
private static final int version;
private static final int majorVersion;
private static final int minorVersion;
@@ -36,6 +37,9 @@ public class VersionHelper {
}
JsonObject json = GsonHelper.parseJsonToJsonObject(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8));
String versionString = json.getAsJsonPrimitive("id").getAsString();
MINECRAFT_VERSION = new MinecraftVersion(versionString);
String[] split = versionString.split("\\.");
int major = Integer.parseInt(split[1]);
int minor = split.length == 3 ? Integer.parseInt(split[2].split("-", 2)[0]) : 0;

View File

@@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G
# Project settings
# Rule: [major update].[feature update].[bug fix]
project_version=0.0.58.1
config_version=38
lang_version=19
config_version=39
lang_version=20
project_group=net.momirealms
latest_supported_version=1.21.6