9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-23 08:59:27 +00:00

Merge branch 'Xiao-MoMi:dev' into dev

This commit is contained in:
jhqwqmc
2025-05-10 02:38:19 +08:00
committed by GitHub
63 changed files with 694 additions and 194 deletions

View File

@@ -192,6 +192,11 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
return PlaceholderAPIUtils.parse((org.bukkit.entity.Player) player.platformPlayer(), text);
}
@Override
public String parse(Player player1, Player player2, String text) {
return PlaceholderAPIUtils.parse((org.bukkit.entity.Player) player1.platformPlayer(), (org.bukkit.entity.Player) player2.platformPlayer(), text);
}
@Override
public int getPlayerProtocolVersion(UUID uuid) {
return ViaVersionUtils.getPlayerProtocolVersion(uuid);

View File

@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.compatibility.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public class PlaceholderAPIUtils {
@@ -12,6 +13,10 @@ public class PlaceholderAPIUtils {
return PlaceholderAPI.setPlaceholders(player, text);
}
public static String parse(Player player1, Player player2, String text) {
return PlaceholderAPI.setRelationalPlaceholders(player1, player2, text);
}
public static void registerExpansions(CraftEngine plugin) {
new ImageExpansion(plugin).register();
new ShiftExpansion(plugin).register();

View File

@@ -62,4 +62,6 @@ categories:
- default:flame_cane
- default:gunpowder_block
- default:solid_gunpowder_block
- default:ender_pearl_flower_seeds
- default:ender_pearl_flower_seeds
- default:gui_head_size_1
- default:gui_head_size_4

View File

@@ -17,6 +17,7 @@ items:
place: minecraft:block.bamboo_wood.place
placement:
ground:
loot-spawn-offset: 0.5,0.5,0
rules:
# ANY / FOUR / EIGHT / SIXTEEN / NORTH / EAST / WEST / SOUTH
rotation: FOUR
@@ -61,6 +62,7 @@ items:
place: minecraft:block.lantern.place
placement:
ground:
loot-spawn-offset: 0,0.2,0
rules:
rotation: ANY
alignment: QUARTER
@@ -111,6 +113,7 @@ items:
place: minecraft:block.bamboo_wood.place
placement:
ground:
loot-spawn-offset: 0,0.4,0
rules:
rotation: ANY
alignment: ANY

View File

@@ -1,4 +1,37 @@
items:
items#gui_head:
default:gui_head_size_1:
material: player_head
custom-model-data: 1000
model:
type: minecraft:special
path: minecraft:item/custom/gui_head_size_1
generation:
parent: minecraft:item/template_skull
gui-light: front
display:
gui:
translation: 0,8,0
scale: 2,2,2
model:
type: minecraft:head
kind: player
default:gui_head_size_4:
material: player_head
custom-model-data: 1001
model:
type: minecraft:special
path: minecraft:item/custom/gui_head_size_4
generation:
parent: minecraft:item/template_skull
gui-light: front
display:
gui:
translation: 9,7,0
scale: 4,4,4
model:
type: minecraft:head
kind: player
items#topaz_gears:
default:topaz_rod:
material: fishing_rod
custom-model-data: 1000

View File

@@ -179,6 +179,8 @@ warning.config.item.model.select.case.missing_model: "<yellow>Issue found in fil
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.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>"
warning.config.item.model.special.invalid_type: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid type '<arg:2>' for model 'minecraft:special'.</yellow>"
warning.config.item.model.special.banner.missing_color: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'color' argument for special model 'minecraft:banner'.</yellow>"
warning.config.item.model.special.bed.missing_texture: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'texture' argument for special model 'minecraft:bed'.</yellow>"
@@ -189,7 +191,6 @@ warning.config.item.model.special.chest.invalid_openness: "<yellow>Issue found i
warning.config.item.model.special.shulker_box.missing_texture: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'texture' argument for special model 'minecraft:shulker_box'.</yellow>"
warning.config.item.model.special.shulker_box.invalid_openness: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using an invalid 'openness' value '<arg:2>' for special model 'minecraft:shulker_box'. Valid range '0~1.'</yellow>"
warning.config.item.model.special.head.missing_kind: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'kind' argument for special model 'minecraft:head'.</yellow>"
warning.config.item.model.special.head.missing_texture: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'texture' argument for special model 'minecraft:head'.</yellow>"
warning.config.block.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated block '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
warning.config.block.missing_state: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'state' argument.</yellow>"
warning.config.block.state.property.missing_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'type' argument for property '<arg:2>'.</yellow>"
@@ -226,6 +227,8 @@ warning.config.block.behavior.strippable.missing_stripped: "<yellow>Issue found
warning.config.block.event.condition.missing_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'type' argument for event condition.</yellow>"
warning.config.block.event.condition.invalid_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an invalid 'type' argument '<arg:2>' for event condition.</yellow>"
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
warning.config.model.generation.invalid_display_position: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid display position '<arg:2>' in 'generation.display' section. Allowed display positions: [<arg:3>]</yellow>"
warning.config.model.generation.invalid_gui_light: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid gui-light option '<arg:2>' in 'generation' section. Allowed gui light options: [<arg:3>]</yellow>"
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
warning.config.model.generation.texture.invalid: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a texture '<arg:2>' with path '<arg:3>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
warning.config.model.generation.parent.invalid: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a parent argument '<arg:2>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"

View File

@@ -167,7 +167,6 @@ warning.config.item.model.special.chest.invalid_openness: "<yellow><arg:0> dosya
warning.config.item.model.special.shulker_box.missing_texture: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:shulker_box' özel modeli için gerekli 'texture' argümanı eksik.</yellow>"
warning.config.item.model.special.shulker_box.invalid_openness: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:shulker_box' özel modeli için geçersiz bir 'openness' değeri '<arg:2>' kullanıyor. Geçerli aralık '0~1.'</yellow>"
warning.config.item.model.special.head.missing_kind: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:head' özel modeli için gerekli 'kind' argümanı eksik.</yellow>"
warning.config.item.model.special.head.missing_texture: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' eşyası, 'minecraft:head' özel modeli için gerekli 'texture' argümanı eksik.</yellow>"
warning.config.block.duplicate: "<yellow><arg:0> dosyasında sorun bulundu - Yinelenen blok '<arg:1>'. Diğer dosyalarda aynı yapılandırmanın olup olmadığını kontrol edin.</yellow>"
warning.config.block.missing_state: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu gerekli 'state' argümanı eksik.</yellow>"
warning.config.block.state.property.missing_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, '<arg:2>' özelliği için gerekli 'type' argümanı eksik.</yellow>"

View File

@@ -179,6 +179,8 @@ warning.config.item.model.select.case.missing_model: "<yellow>在文件 <arg:0>
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.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>"
warning.config.item.model.special.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:special' 模型使用了无效类型 '<arg:2>'</yellow>"
warning.config.item.model.special.banner.missing_color: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:banner' 特殊模型缺少必需的 'color' 参数</yellow>"
warning.config.item.model.special.bed.missing_texture: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:bed' 特殊模型缺少必需的 'texture' 参数</yellow>"
@@ -189,7 +191,6 @@ warning.config.item.model.special.chest.invalid_openness: "<yellow>在文件 <ar
warning.config.item.model.special.shulker_box.missing_texture: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:shulker_box' 特殊模型缺少必需的 'texture' 参数</yellow>"
warning.config.item.model.special.shulker_box.invalid_openness: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:shulker_box' 特殊模型使用了无效的 'openness' 值 '<arg:2>' 有效范围应为 0~1</yellow>"
warning.config.item.model.special.head.missing_kind: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:head' 特殊模型缺少必需的 'kind' 参数</yellow>"
warning.config.item.model.special.head.missing_texture: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'minecraft:head' 特殊模型缺少必需的 'texture' 参数</yellow>"
warning.config.block.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的方块 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
warning.config.block.missing_state: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 缺少必需的 'state' 参数</yellow>"
warning.config.block.state.property.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的属性 '<arg:2>' 缺少必需的 'type' 参数</yellow>"
@@ -227,6 +228,8 @@ warning.config.block.event.condition.missing_type: "<yellow>在文件 <arg:0> -
warning.config.block.event.condition.invalid_type: "<yellow>在文件 <arg:0> - 方块 '<arg:1>' 使用了无效的事件条件类型 '<arg:2>'</yellow>"
warning.config.model.generation.missing_parent: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'generation' 段落缺少必需的 'parent' 参数</yellow>"
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 发现问题 - 无法为 '<arg:1>' 生成模型 存在多个配置尝试使用相同路径 '<arg:2>' 生成不同的 JSON 模型</yellow>"
warning.config.model.generation.invalid_display_position: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 在 'generation.display' 区域使用了无效的 display 位置类型 '<arg:2>'. 可用展示类型: [<arg:3>]</yellow>"
warning.config.model.generation.invalid_gui_light: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 在 'generation' 区域使用了无效的GUI光照 '<arg:2>'. 可用GUI光照: [<arg:3>]</yellow>"
warning.config.model.generation.texture.invalid: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的纹理 '<arg:2>' 路径 '<arg:3>' 包含非法字符 请参考 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>"
warning.config.model.generation.parent.invalid: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的父级参数 '<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>"
warning.config.emoji.missing_keywords: "<yellow>在文件 <arg:0> 发现问题 - 表情 '<arg:1>' 缺少必需的 'keywords' 参数</yellow>"

View File

@@ -6,7 +6,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.core.advancement.AbstractAdvancementManager;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.GsonHelper;
import net.momirealms.craftengine.core.util.Key;
@@ -31,11 +31,11 @@ public class BukkitAdvancementManager extends AbstractAdvancementManager {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.advancementParser;
}
public class AdvancementParser implements ConfigSectionParser {
public class AdvancementParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"advancements", "advancement"};
@Override

View File

@@ -263,7 +263,7 @@ public final class CraftEngineFurniture {
@Nullable net.momirealms.craftengine.core.entity.player.Player player,
boolean dropLoot,
boolean playSound) {
Location location = loadedFurniture.location();
Location location = loadedFurniture.dropLocation();
loadedFurniture.destroy();
LootTable<ItemStack> lootTable = (LootTable<ItemStack>) loadedFurniture.config().lootTable();
Vec3d vec3d = LocationUtils.toVec3d(location);

View File

@@ -25,7 +25,7 @@ import net.momirealms.craftengine.core.pack.ResourceLocation;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
@@ -193,7 +193,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.blockParser;
}
@@ -314,7 +314,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
}
}
public class BlockParser implements ConfigSectionParser {
public class BlockParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"blocks", "block"};
@Override
@@ -537,7 +537,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
if (singleModelMap.containsKey("weight")) json.addProperty("weight", ResourceConfigUtils.getAsInt(singleModelMap.get("weight"), "weight"));
Map<String, Object> generationMap = MiscUtils.castToMap(singleModelMap.get("generation"), true);
if (generationMap != null) {
prepareModelGeneration(new ModelGeneration(Key.of(modelPath), generationMap));
prepareModelGeneration(ModelGeneration.of(Key.of(modelPath), generationMap));
}
variants.add(json);
}

View File

@@ -11,7 +11,7 @@ import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.Key;
@@ -86,11 +86,11 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.furnitureParser;
}
public class FurnitureParser implements ConfigSectionParser {
public class FurnitureParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] { "furniture" };
@Override
@@ -124,6 +124,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH));
Map<String, Object> placementArguments = MiscUtils.castToMap(entry.getValue(), true);
Optional<Vector3f> optionalLootSpawnOffset = Optional.ofNullable(placementArguments.get("loot-spawn-offset")).map(it -> MiscUtils.getAsVector3f(it, "loot-spawn-offset"));
// furniture display elements
List<FurnitureElement> elements = new ArrayList<>();
List<Map<String, Object>> elementConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("elements", List.of());
@@ -178,7 +180,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
hitboxes.toArray(new HitBox[0]),
rotationRule,
alignmentRule,
externalModel
externalModel,
optionalLootSpawnOffset
));
} else {
placements.put(anchorType, new CustomFurniture.Placement(
@@ -186,7 +189,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
hitboxes.toArray(new HitBox[0]),
RotationRule.ANY,
AlignmentRule.CENTER,
externalModel
externalModel,
optionalLootSpawnOffset
));
}
}

View File

@@ -75,9 +75,9 @@ public class LoadedFurniture implements Furniture {
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id, e);
}
hasExternalModel = true;
this.hasExternalModel = true;
} else {
hasExternalModel = false;
this.hasExternalModel = false;
}
float yaw = this.location.getYaw();
@@ -176,6 +176,17 @@ public class LoadedFurniture implements Furniture {
return baseEntity().isValid();
}
@NotNull
public Location dropLocation() {
Optional<Vector3f> dropOffset = config().getPlacement(this.anchorType).dropOffset();
if (dropOffset.isEmpty()) {
return location();
}
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate();
Vector3f offset = conjugated.transform(new Vector3f(dropOffset.get()));
return new Location(this.location.getWorld(), this.location.getX() + offset.x, this.location.getY() + offset.y, this.location.getZ() - offset.z);
}
@Override
public void destroy() {
if (!isValid()) {

View File

@@ -27,7 +27,7 @@ import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.select.ChargeTypeSelectProperty;
import net.momirealms.craftengine.core.pack.model.select.TrimMaterialSelectProperty;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
@@ -164,7 +164,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.itemParser;
}
@@ -224,7 +224,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
return wrapped.id();
}
public class ItemParser implements ConfigSectionParser {
public class ItemParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"items", "item"};
@Override
@@ -463,6 +463,12 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
baseModel.path(),
customModelData
));
} else if (currentModel instanceof SpecialItemModel specialModel) {
resultList.add(new LegacyOverridesModel(
new LinkedHashMap<>(accumulatedPredicates),
specialModel.base(),
customModelData
));
}
}

View File

@@ -39,7 +39,7 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
case "1.21.4" -> {
return new ComponentItemFactory1_21_4(plugin);
}
case "1.21.5", "1.22", "1.22.1" -> {
case "1.21.5", "1.21.6", "1.22", "1.22.1" -> {
return new ComponentItemFactory1_21_5(plugin);
}
default -> throw new IllegalStateException("Unsupported server version: " + plugin.serverVersion());

View File

@@ -12,7 +12,7 @@ import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.loot.VanillaLoot;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
@@ -87,11 +87,11 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.vanillaLootParser;
}
public class VanillaLootParser implements ConfigSectionParser {
public class VanillaLootParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"vanilla-loots", "vanilla-loot", "loots", "loot"};
@Override

View File

@@ -1,9 +1,9 @@
package net.momirealms.craftengine.core.advancement;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
public interface AdvancementManager extends Manageable {
ConfigSectionParser parser();
ConfigParser parser();
}

View File

@@ -4,7 +4,7 @@ import com.google.gson.JsonElement;
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
import net.momirealms.craftengine.core.pack.model.generation.ModelGenerator;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
import org.incendo.cloud.suggestion.Suggestion;
@@ -14,7 +14,7 @@ import java.util.Optional;
public interface BlockManager extends Manageable, ModelGenerator {
ConfigSectionParser parser();
ConfigParser parser();
Collection<ModelGeneration> modelsToGenerate();

View File

@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import java.util.EnumMap;
import java.util.Optional;
@@ -60,6 +61,7 @@ public class CustomFurniture {
HitBox[] hitBoxes,
RotationRule rotationRule,
AlignmentRule alignmentRule,
Optional<ExternalModel> externalModel) {
Optional<ExternalModel> externalModel,
Optional<Vector3f> dropOffset) {
}
}

View File

@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.entity.Entity;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
@@ -15,7 +15,7 @@ import java.util.Optional;
public interface FurnitureManager extends Manageable {
String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin";
ConfigSectionParser parser();
ConfigParser parser();
void initSuggestions();

View File

@@ -6,7 +6,7 @@ import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.pack.ResourceLocation;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
@@ -75,8 +75,8 @@ public abstract class AbstractFontManager implements FontManager {
}
@Override
public ConfigSectionParser[] parsers() {
return new ConfigSectionParser[] {this.imageParser, this.emojiParser};
public ConfigParser[] parsers() {
return new ConfigParser[] {this.imageParser, this.emojiParser};
}
@Override
@@ -339,7 +339,7 @@ public abstract class AbstractFontManager implements FontManager {
return this.fonts.computeIfAbsent(key, Font::new);
}
public class EmojiParser implements ConfigSectionParser {
public class EmojiParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"emoji", "emojis"};
@Override
@@ -400,7 +400,7 @@ public abstract class AbstractFontManager implements FontManager {
}
}
public class ImageParser implements ConfigSectionParser {
public class ImageParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"images", "image"};
@Override

View File

@@ -4,7 +4,7 @@ import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.CharacterUtils;
import net.momirealms.craftengine.core.util.FormatUtils;
@@ -45,7 +45,7 @@ public interface FontManager extends Manageable {
IllegalCharacterProcessResult processIllegalCharacters(String raw, char replacement);
ConfigSectionParser[] parsers();
ConfigParser[] parsers();
default EmojiTextProcessResult replaceMiniMessageEmoji(@NotNull String miniMessage, @Nullable Player player) {
return replaceMiniMessageEmoji(miniMessage, player, Config.maxEmojisPerParse());

View File

@@ -7,7 +7,7 @@ import net.momirealms.craftengine.core.pack.model.ItemModel;
import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel;
import net.momirealms.craftengine.core.pack.model.generation.ModelGenerator;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.registry.Holder;
import net.momirealms.craftengine.core.util.Key;
import org.incendo.cloud.suggestion.Suggestion;
@@ -17,7 +17,7 @@ import java.util.*;
public interface ItemManager<T> extends Manageable, ModelGenerator {
ConfigSectionParser parser();
ConfigParser parser();
Map<Key, TreeSet<LegacyOverridesModel>> legacyItemOverrides();

View File

@@ -9,7 +9,7 @@ import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.Holder;
import net.momirealms.craftengine.core.util.Key;
@@ -35,7 +35,7 @@ public abstract class AbstractRecipeManager<T> implements RecipeManager<T> {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.recipeParser;
}
@@ -140,7 +140,7 @@ public abstract class AbstractRecipeManager<T> implements RecipeManager<T> {
}
}
public class RecipeParser implements ConfigSectionParser {
public class RecipeParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"recipes", "recipe"};
@Override

View File

@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.item.recipe;
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.Nullable;
@@ -11,7 +11,7 @@ import java.util.Optional;
public interface RecipeManager<T> extends Manageable {
ConfigSectionParser parser();
ConfigParser parser();
boolean isDataPackRecipe(Key key);

View File

@@ -1,14 +1,14 @@
package net.momirealms.craftengine.core.loot;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
import java.util.Optional;
public interface VanillaLootManager extends Manageable {
ConfigSectionParser parser();
ConfigParser parser();
Optional<VanillaLoot> getBlockLoot(int blockState);

View File

@@ -19,7 +19,7 @@ import net.momirealms.craftengine.core.pack.model.generation.ModelGenerator;
import net.momirealms.craftengine.core.pack.obfuscation.ObfA;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.config.StringKeyConstructor;
import net.momirealms.craftengine.core.plugin.locale.I18NData;
import net.momirealms.craftengine.core.plugin.locale.LocalizedException;
@@ -70,8 +70,8 @@ public abstract class AbstractPackManager implements PackManager {
private final CraftEngine plugin;
private final BiConsumer<Path, Path> eventDispatcher;
private final Map<String, Pack> loadedPacks = new HashMap<>();
private final Map<String, ConfigSectionParser> sectionParsers = new HashMap<>();
private final TreeMap<ConfigSectionParser, List<CachedConfig>> cachedConfigs = new TreeMap<>();
private final Map<String, ConfigParser> sectionParsers = new HashMap<>();
private final TreeMap<ConfigParser, List<CachedConfig>> cachedConfigs = new TreeMap<>();
protected BiConsumer<Path, Path> zipGenerator;
protected ResourcePackHost resourcePackHost;
@@ -211,7 +211,7 @@ public abstract class AbstractPackManager implements PackManager {
}
@Override
public boolean registerConfigSectionParser(ConfigSectionParser parser) {
public boolean registerConfigSectionParser(ConfigParser parser) {
for (String id : parser.sectionId()) {
if (this.sectionParsers.containsKey(id)) return false;
}
@@ -404,7 +404,7 @@ public abstract class AbstractPackManager implements PackManager {
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/gui/sprites/tooltip/topaz_frame.png.mcmeta");
}
private void loadResourceConfigs(Predicate<ConfigSectionParser> predicate) {
private void loadResourceConfigs(Predicate<ConfigParser> predicate) {
long o1 = System.nanoTime();
for (Pack pack : loadedPacks()) {
if (!pack.enabled()) continue;
@@ -435,8 +435,8 @@ public abstract class AbstractPackManager implements PackManager {
}
long o2 = System.nanoTime();
this.plugin.logger().info("Loaded packs. Took " + String.format("%.2f", ((o2 - o1) / 1_000_000.0)) + " ms");
for (Map.Entry<ConfigSectionParser, List<CachedConfig>> entry : this.cachedConfigs.entrySet()) {
ConfigSectionParser parser = entry.getKey();
for (Map.Entry<ConfigParser, List<CachedConfig>> entry : this.cachedConfigs.entrySet()) {
ConfigParser parser = entry.getKey();
long t1 = System.nanoTime();
for (CachedConfig cached : entry.getValue()) {
for (Map.Entry<String, Object> configEntry : cached.config().entrySet()) {
@@ -444,8 +444,8 @@ public abstract class AbstractPackManager implements PackManager {
try {
Key id = Key.withDefaultNamespace(key, cached.pack().namespace());
try {
if (parser.isTemplate()) {
this.plugin.templateManager().addTemplate(cached.pack(), cached.filePath(), id, configEntry.getValue());
if (parser.supportsParsingObject()) {
parser.parseObject(cached.pack(), cached.filePath(), id, configEntry.getValue());
} else if (predicate.test(parser)) {
if (configEntry.getValue() instanceof Map<?, ?> configSection0) {
Map<String, Object> configSection1 = castToMap(configSection0, false);
@@ -832,7 +832,7 @@ public abstract class AbstractPackManager implements PackManager {
}
try (BufferedWriter writer = Files.newBufferedWriter(modelPath)) {
GsonHelper.get().toJson(generation.getJson(), writer);
GsonHelper.get().toJson(generation.get(), writer);
} catch (IOException e) {
plugin.logger().warn("Failed to generate model: " + modelPath.toAbsolutePath(), e);
}

View File

@@ -2,17 +2,18 @@ package net.momirealms.craftengine.core.pack;
public class LoadingSequence {
public static final int TEMPLATE = 0;
public static final int LANG = 10;
public static final int TRANSLATION = 20;
public static final int BLOCK = 30;
public static final int ITEM = 40;
public static final int FURNITURE = 50;
public static final int IMAGE = 60;
public static final int RECIPE = 70;
public static final int CATEGORY = 80;
public static final int SOUND = 90;
public static final int JUKEBOX_SONG = 100;
public static final int VANILLA_LOOTS = 110;
public static final int EMOJI = 120;
public static final int ADVANCEMENT = 130;
public static final int GLOBAL_VAR = 10;
public static final int LANG = 20;
public static final int TRANSLATION = 30;
public static final int BLOCK = 40;
public static final int ITEM = 50;
public static final int FURNITURE = 60;
public static final int IMAGE = 70;
public static final int RECIPE = 80;
public static final int CATEGORY = 90;
public static final int SOUND = 100;
public static final int JUKEBOX_SONG = 110;
public static final int VANILLA_LOOTS = 120;
public static final int EMOJI = 130;
public static final int ADVANCEMENT = 140;
}

View File

@@ -3,7 +3,7 @@ package net.momirealms.craftengine.core.pack;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
@@ -16,17 +16,17 @@ public interface PackManager extends Manageable {
@NotNull
Collection<Pack> loadedPacks();
boolean registerConfigSectionParser(ConfigSectionParser parser);
boolean registerConfigSectionParser(ConfigParser parser);
default void registerConfigSectionParsers(ConfigSectionParser[] parsers) {
for (ConfigSectionParser parser : parsers) {
default void registerConfigSectionParsers(ConfigParser[] parsers) {
for (ConfigParser parser : parsers) {
registerConfigSectionParser(parser);
}
}
boolean unregisterConfigSectionParser(String id);
default void unregisterConfigSectionParser(ConfigSectionParser parser) {
default void unregisterConfigSectionParser(ConfigParser parser) {
for (String id : parser.sectionId()) {
unregisterConfigSectionParser(id);
}

View File

@@ -77,7 +77,7 @@ public class BaseItemModel implements ItemModel {
Map<String, Object> generation = MiscUtils.castToMap(arguments.get("generation"), true);
ModelGeneration modelGeneration = null;
if (generation != null) {
modelGeneration = new ModelGeneration(Key.of(modelPath), generation);
modelGeneration = ModelGeneration.of(Key.of(modelPath), generation);
}
if (arguments.containsKey("tints")) {
List<Tint> tints = new ArrayList<>();

View File

@@ -1,24 +1,29 @@
package net.momirealms.craftengine.core.pack.model;
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.special.SpecialModel;
import net.momirealms.craftengine.core.pack.model.special.SpecialModels;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class SpecialItemModel implements ItemModel {
public static final Factory FACTORY = new Factory();
private final SpecialModel specialModel;
private final String base;
private final ModelGeneration modelGeneration;
public SpecialItemModel(SpecialModel specialModel, String base) {
public SpecialItemModel(SpecialModel specialModel, String base, @Nullable ModelGeneration generation) {
this.specialModel = specialModel;
this.base = base;
this.modelGeneration = generation;
}
public SpecialModel specialModel() {
@@ -45,16 +50,28 @@ public class SpecialItemModel implements ItemModel {
@Override
public List<ModelGeneration> modelsToGenerate() {
return List.of();
if (this.modelGeneration == null) {
return List.of();
} else {
return List.of(this.modelGeneration);
}
}
public static class Factory implements ItemModelFactory {
@Override
public ItemModel create(Map<String, Object> arguments) {
String base = Objects.requireNonNull(arguments.get("base")).toString();
String base = ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "base", "path"), "warning.config.item.model.special.missing_path");
if (!ResourceLocation.isValid(base)) {
throw new LocalizedResourceConfigException("warning.config.item.model.special.invalid_path", base);
}
Map<String, Object> generation = MiscUtils.castToMap(arguments.get("generation"), true);
ModelGeneration modelGeneration = null;
if (generation != null) {
modelGeneration = ModelGeneration.of(Key.of(base), generation);
}
Map<String, Object> model = MiscUtils.castToMap(arguments.get("model"), false);
return new SpecialItemModel(SpecialModels.fromMap(model), base);
return new SpecialItemModel(SpecialModels.fromMap(model), base, modelGeneration);
}
}
}

View File

@@ -38,9 +38,14 @@ public abstract class AbstractModelGenerator implements ModelGenerator {
if (!ResourceLocation.isValid(model.parentModelPath())) {
throw new LocalizedResourceConfigException("warning.config.model.generation.parent.invalid", model.parentModelPath());
}
for (Map.Entry<String, String> texture : model.texturesOverride().entrySet()) {
if (!ResourceLocation.isValid(texture.getValue())) {
throw new LocalizedResourceConfigException("warning.config.model.generation.texture.invalid", texture.getKey(), texture.getValue());
Map<String, String> textures = model.texturesOverride();
if (textures != null) {
for (Map.Entry<String, String> texture : textures.entrySet()) {
if (texture.getValue().charAt(0) != '#') {
if (!ResourceLocation.isValid(texture.getValue())) {
throw new LocalizedResourceConfigException("warning.config.model.generation.texture.invalid", texture.getKey(), texture.getValue());
}
}
}
}
this.modelsToGenerate.put(model.path(), model);

View File

@@ -0,0 +1,5 @@
package net.momirealms.craftengine.core.pack.model.generation;
public enum GuiLight {
FRONT, SIDE
}

View File

@@ -1,44 +1,107 @@
package net.momirealms.craftengine.core.pack.model.generation;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.momirealms.craftengine.core.pack.model.generation.display.DisplayMeta;
import net.momirealms.craftengine.core.pack.model.generation.display.DisplayPosition;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.EnumUtils;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public class ModelGeneration {
public class ModelGeneration implements Supplier<JsonObject> {
private static final Map<String, BiConsumer<Builder, Object>> BUILDER_FUNCTIONS = new HashMap<>();
static {
BUILDER_FUNCTIONS.put("textures", (b, data) -> {
Map<String, Object> texturesMap = MiscUtils.castToMap(data, false);
Map<String, String> texturesOverride = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : texturesMap.entrySet()) {
if (entry.getValue() instanceof String p) {
texturesOverride.put(entry.getKey(), p);
}
}
b.texturesOverride(texturesOverride);
});
BUILDER_FUNCTIONS.put("display", (b, data) -> {
Map<String, Object> displayMap = MiscUtils.castToMap(data, false);
Map<DisplayPosition, DisplayMeta> displays = new EnumMap<>(DisplayPosition.class);
for (Map.Entry<String, Object> entry : displayMap.entrySet()) {
try {
DisplayPosition displayPosition = DisplayPosition.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH));
if (entry.getValue() instanceof Map<?,?> metaMap) {
displays.put(displayPosition, DisplayMeta.fromMap(MiscUtils.castToMap(metaMap, false)));
}
} catch (IllegalArgumentException e) {
throw new LocalizedResourceConfigException("warning.config.model.generation.invalid_display_position", e, entry.getKey(), EnumUtils.toString(DisplayPosition.values()));
}
}
b.displays(displays);
});
BUILDER_FUNCTIONS.put("gui-light", (b, data) -> {
String guiLightStr = String.valueOf(data);
try {
GuiLight guiLight = GuiLight.valueOf(guiLightStr.toUpperCase(Locale.ENGLISH));
b.guiLight(guiLight);
} catch (IllegalArgumentException e) {
throw new LocalizedResourceConfigException("warning.config.model.generation.invalid_gui_light", e, guiLightStr, EnumUtils.toString(GuiLight.values()));
}
});
BUILDER_FUNCTIONS.put("ambient-occlusion", (b, data) -> {
b.ambientOcclusion((boolean) data);
});
BUILDER_FUNCTIONS.put("parent", (b, data) -> {
String parentModelPath = data.toString();
b.parentModelPath(parentModelPath);
});
}
@NotNull
private final Key path;
@NotNull
private final String parentModelPath;
@Nullable
private final Map<String, String> texturesOverride;
@Nullable
private final Map<DisplayPosition, DisplayMeta> displays;
@Nullable
private final GuiLight guiLight;
@Nullable
private final Boolean ambientOcclusion;
@Nullable
private JsonObject cachedModel;
public ModelGeneration(Key path, String parentModelPath, Map<String, String> texturesOverride) {
public ModelGeneration(@NotNull Key path,
@NotNull String parentModelPath,
@Nullable Map<String, String> texturesOverride,
@Nullable Map<DisplayPosition, DisplayMeta> displays,
@Nullable GuiLight guiLight,
@Nullable Boolean ambientOcclusion) {
this.path = path;
this.parentModelPath = parentModelPath;
this.texturesOverride = texturesOverride;
this.displays = displays;
this.guiLight = guiLight;
this.ambientOcclusion = ambientOcclusion;
}
public ModelGeneration(Key path, Map<String, Object> map) {
this.path = path;
Object parent = map.get("parent");
if (parent == null) {
throw new LocalizedResourceConfigException("warning.config.model.generation.missing_parent");
}
this.parentModelPath = parent.toString();
Map<String, Object> texturesMap = MiscUtils.castToMap(map.get("textures"), true);
if (texturesMap != null) {
this.texturesOverride = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : texturesMap.entrySet()) {
if (entry.getValue() instanceof String p) {
this.texturesOverride.put(entry.getKey(), p);
}
}
} else {
this.texturesOverride = Collections.emptyMap();
public static ModelGeneration of(Key path, Map<String, Object> map) {
Builder builder = builder().path(path);
for (Map.Entry<String, Object> entry : map.entrySet()) {
Optional.ofNullable(BUILDER_FUNCTIONS.get(entry.getKey())).ifPresent(it -> it.accept(builder, entry.getValue()));
}
return builder.build();
}
@Nullable
public Map<String, String> texturesOverride() {
return texturesOverride;
}
public Key path() {
@@ -49,36 +112,137 @@ public class ModelGeneration {
return parentModelPath;
}
public Map<String, String> texturesOverride() {
return texturesOverride;
@Nullable
public Map<DisplayPosition, DisplayMeta> displays() {
return displays;
}
public JsonObject getJson() {
@Nullable
public GuiLight guiLight() {
return guiLight;
}
@Nullable
public Boolean ambientOcclusion() {
return ambientOcclusion;
}
@Override
public JsonObject get() {
if (this.cachedModel == null) {
this.cachedModel = this.getCachedModel();
}
return this.cachedModel;
}
private JsonObject getCachedModel() {
JsonObject model = new JsonObject();
model.addProperty("parent", parentModelPath);
if (this.texturesOverride != null && !this.texturesOverride.isEmpty()) {
model.addProperty("parent", this.parentModelPath);
if (this.texturesOverride != null) {
JsonObject textures = new JsonObject();
for (Map.Entry<String, String> entry : this.texturesOverride.entrySet()) {
textures.addProperty(entry.getKey(), entry.getValue());
}
model.add("textures", textures);
}
if (this.displays != null) {
JsonObject displays = new JsonObject();
for (Map.Entry<DisplayPosition, DisplayMeta> entry : this.displays.entrySet()) {
JsonObject displayMetadata = new JsonObject();
DisplayMeta meta = entry.getValue();
if (meta.rotation() != null)
displayMetadata.add("rotation", vectorToJsonArray(meta.rotation()));
if (meta.translation() != null)
displayMetadata.add("translation", vectorToJsonArray(meta.translation()));
if (meta.scale() != null)
displayMetadata.add("scale", vectorToJsonArray(meta.scale()));
displays.add(entry.getKey().name().toLowerCase(Locale.ENGLISH), displayMetadata);
}
model.add("display", displays);
}
if (this.guiLight != null) {
model.addProperty("gui_light", this.guiLight.name().toLowerCase(Locale.ENGLISH));
}
return model;
}
private JsonArray vectorToJsonArray(Vector3f vector) {
JsonArray array = new JsonArray();
array.add(vector.x());
array.add(vector.y());
array.add(vector.z());
return array;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ModelGeneration that = (ModelGeneration) o;
return this.path.equals(that.path) && parentModelPath.equals(that.parentModelPath) && Objects.equals(texturesOverride, that.texturesOverride);
return this.path.equals(that.path) && parentModelPath.equals(that.parentModelPath) && Objects.equals(texturesOverride, that.texturesOverride)
&& Objects.equals(displays, that.displays) && Objects.equals(ambientOcclusion, that.ambientOcclusion) && Objects.equals(guiLight, that.guiLight);
}
@Override
public int hashCode() {
int result = path.hashCode();
result = 31 * result + parentModelPath.hashCode();
result = 31 * result + texturesOverride.hashCode();
int result = this.path.hashCode();
result = 31 * result + this.parentModelPath.hashCode();
return result;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private Key path;
private String parentModelPath;
@Nullable
private Map<String, String> texturesOverride;
@Nullable
private Map<DisplayPosition, DisplayMeta> displays;
@Nullable
private GuiLight guiLight;
@Nullable
private Boolean ambientOcclusion;
public Builder() {}
public Builder path(Key key) {
this.path = key;
return this;
}
public Builder parentModelPath(String parentModelPath) {
this.parentModelPath = parentModelPath;
return this;
}
public Builder texturesOverride(Map<String, String> texturesOverride) {
this.texturesOverride = texturesOverride;
return this;
}
public Builder displays(Map<DisplayPosition, DisplayMeta> displays) {
this.displays = displays;
return this;
}
public Builder guiLight(GuiLight guiLight) {
this.guiLight = guiLight;
return this;
}
public Builder ambientOcclusion(Boolean ambientOcclusion) {
this.ambientOcclusion = ambientOcclusion;
return this;
}
public ModelGeneration build() {
if (this.parentModelPath == null) {
throw new LocalizedResourceConfigException("warning.config.model.generation.missing_parent");
}
return new ModelGeneration(Objects.requireNonNull(this.path, "path should be nonnull"), this.parentModelPath, this.texturesOverride, this.displays, this.guiLight, this.ambientOcclusion);
}
}
}

View File

@@ -0,0 +1,25 @@
package net.momirealms.craftengine.core.pack.model.generation.display;
import net.momirealms.craftengine.core.util.MiscUtils;
import org.joml.Vector3f;
import java.util.Map;
public record DisplayMeta(Vector3f rotation, Vector3f translation, Vector3f scale) {
public static DisplayMeta fromMap(Map<String, Object> map) {
Vector3f rotation = null;
if (map.containsKey("rotation")) {
rotation = MiscUtils.getAsVector3f(map.get("rotation"), "rotation");
}
Vector3f translation = null;
if (map.containsKey("translation")) {
translation = MiscUtils.getAsVector3f(map.get("translation"), "translation");
}
Vector3f scale = null;
if (map.containsKey("scale")) {
scale = MiscUtils.getAsVector3f(map.get("scale"), "scale");
}
return new DisplayMeta(rotation, translation, scale);
}
}

View File

@@ -0,0 +1,12 @@
package net.momirealms.craftengine.core.pack.model.generation.display;
public enum DisplayPosition {
THIRDPERSON_RIGHTHAND,
THIRDPERSON_LEFTHAND,
FIRSTPERSON_RIGHTHAND,
FIRSTPERSON_LEFTHAND,
GUI,
HEAD,
GROUND,
FIXED
}

View File

@@ -27,7 +27,9 @@ public class ChestSpecialModel implements SpecialModel {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("texture", texture);
json.addProperty("openness", openness);
if (openness > 0) {
json.addProperty("openness", openness);
}
return json;
}

View File

@@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
import java.util.Optional;
public class HeadSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
@@ -28,8 +29,12 @@ public class HeadSpecialModel implements SpecialModel {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("kind", kind);
json.addProperty("texture", texture);
json.addProperty("animation", animation);
if (texture != null) {
json.addProperty("texture", texture);
}
if (animation != 0) {
json.addProperty("animation", animation);
}
return json;
}
@@ -38,7 +43,7 @@ public class HeadSpecialModel implements SpecialModel {
@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 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("texture"), "warning.config.item.model.special.head.missing_texture");
String texture = Optional.ofNullable(arguments.get("texture")).map(String::valueOf).orElse(null);
int animation = ResourceConfigUtils.getAsInt(arguments.getOrDefault("animation", 0), "animation");
return new HeadSpecialModel(kind, texture, animation);
}

View File

@@ -5,9 +5,11 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
public class ShulkerBoxSpecialModel implements SpecialModel {
public static final Factory FACTORY = new Factory();
@@ -15,7 +17,7 @@ public class ShulkerBoxSpecialModel implements SpecialModel {
private final float openness;
private final Direction orientation;
public ShulkerBoxSpecialModel(String texture, float openness, Direction orientation) {
public ShulkerBoxSpecialModel(String texture, float openness, @Nullable Direction orientation) {
this.texture = texture;
this.openness = openness;
this.orientation = orientation;
@@ -31,8 +33,10 @@ public class ShulkerBoxSpecialModel implements SpecialModel {
JsonObject json = new JsonObject();
json.addProperty("type", type().toString());
json.addProperty("texture", texture);
if (orientation != null) {
json.addProperty("orientation", orientation.name().toLowerCase(Locale.ENGLISH));
}
json.addProperty("openness", openness);
json.addProperty("orientation", orientation.name().toLowerCase(Locale.ENGLISH));
return json;
}
@@ -42,7 +46,7 @@ public class ShulkerBoxSpecialModel implements SpecialModel {
public SpecialModel create(Map<String, Object> arguments) {
float openness = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("openness", 0), "openness");
String texture = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("texture"), "warning.config.item.model.special.shulker_box.missing_texture");
Direction orientation = Direction.valueOf(arguments.getOrDefault("orientation", "down").toString().toUpperCase(Locale.ENGLISH));
Direction orientation = Optional.ofNullable(arguments.get("orientation")).map(String::valueOf).map(String::toUpperCase).map(Direction::valueOf).orElse(null);
if (openness > 1 || openness < 0) {
throw new LocalizedResourceConfigException("warning.config.item.model.special.shulker_box.invalid_openness", String.valueOf(openness));
}

View File

@@ -10,9 +10,9 @@ import java.util.Map;
public class ConstantTint implements Tint {
public static final Factory FACTORY = new Factory();
private final Either<Integer, List<Integer>> value;
private final Either<Integer, List<Float>> value;
public ConstantTint(Either<Integer, List<Integer>> value) {
public ConstantTint(Either<Integer, List<Float>> value) {
this.value = value;
}

View File

@@ -10,10 +10,10 @@ import java.util.Map;
public class CustomModelDataTint implements Tint {
public static final Factory FACTORY = new Factory();
private final Either<Integer, List<Integer>> value;
private final Either<Integer, List<Float>> value;
private final int index;
public CustomModelDataTint(Either<Integer, List<Integer>> value, int index) {
public CustomModelDataTint(Either<Integer, List<Float>> value, int index) {
this.index = index;
this.value = value;
}

View File

@@ -9,10 +9,10 @@ import java.util.Map;
public class SimpleDefaultTint implements Tint {
public static final Factory FACTORY = new Factory();
private final Either<Integer, List<Integer>> value;
private final Either<Integer, List<Float>> value;
private final Key type;
public SimpleDefaultTint(Either<Integer, List<Integer>> value, Key type) {
public SimpleDefaultTint(Either<Integer, List<Float>> value, Key type) {
this.value = value;
this.type = type;
}

View File

@@ -12,16 +12,16 @@ public interface Tint extends Supplier<JsonObject> {
Key type();
default void applyAnyTint(JsonObject json, Either<Integer, List<Integer>> value, String key) {
default void applyAnyTint(JsonObject json, Either<Integer, List<Float>> value, String key) {
if (value.primary().isPresent()) {
json.addProperty(key, value.primary().get());
} else {
List<Integer> list = value.fallback().get();
List<Float> list = value.fallback().get();
if (list.size() != 3) {
throw new RuntimeException("Invalid tint value list size: " + list.size() + " which is expected to be 3");
}
JsonArray array = new JsonArray();
for (int i : list) {
for (float i : list) {
array.add(i);
}
json.add(key, array);

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.core.pack.model.tint;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.MiscUtils;
import org.incendo.cloud.type.Either;
import java.util.ArrayList;
@@ -11,27 +12,51 @@ public interface TintFactory {
Tint create(Map<String, Object> arguments);
default Either<Integer, List<Integer>> parseTintValue(Object value) {
default Either<Integer, List<Float>> parseTintValue(Object value) {
if (value instanceof Number i) {
return Either.ofPrimary(i.intValue());
} else if (value instanceof List<?> list) {
if (list.size() == 3) {
List<Integer> intList = new ArrayList<>();
for (Object o : list) {
intList.add(Integer.parseInt(o.toString()));
List<String> strList = MiscUtils.getAsStringList(list);
boolean hasDot = false;
for (String str : strList) {
if (str.contains(".")) {
hasDot = true;
break;
}
}
return Either.ofFallback(intList);
List<Float> fList = new ArrayList<>();
for (String str : strList) {
if (hasDot) {
fList.add(Float.parseFloat(str));
} else {
fList.add(convertToFloat(Integer.parseInt(str)));
}
}
return Either.ofFallback(fList);
}
} else if (value instanceof String s) {
String[] split = s.split(",");
if (split.length == 3) {
List<Integer> intList = new ArrayList<>();
List<Float> fList = new ArrayList<>();
boolean hasDot = s.contains(".");
for (String string : split) {
intList.add(Integer.parseInt(string));
if (hasDot) {
fList.add(Float.parseFloat(string));
} else {
fList.add(convertToFloat(Integer.parseInt(string)));
}
}
return Either.ofFallback(intList);
return Either.ofFallback(fList);
}
}
throw new LocalizedResourceConfigException("warning.config.item.model.tint.invalid_value", value.toString());
}
static float convertToFloat(int value) {
if (value < 0 || value > 255) {
throw new IllegalArgumentException("Tint value out of range: " + value + ". Allowed range is [0,255]");
}
return value / 255.0f;
}
}

View File

@@ -27,5 +27,7 @@ public interface CompatibilityManager {
String parse(Player player, String text);
String parse(Player player1, Player player2, String text);
int getPlayerProtocolVersion(UUID uuid);
}

View File

@@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.template.TemplateManager;
import net.momirealms.craftengine.core.plugin.config.template.TemplateManagerImpl;
import net.momirealms.craftengine.core.plugin.context.GlobalVariableManager;
import net.momirealms.craftengine.core.plugin.dependency.Dependencies;
import net.momirealms.craftengine.core.plugin.dependency.Dependency;
import net.momirealms.craftengine.core.plugin.dependency.DependencyManager;
@@ -68,6 +69,7 @@ public abstract class CraftEngine implements Plugin {
protected VanillaLootManager vanillaLootManager;
protected AdvancementManager advancementManager;
protected CompatibilityManager compatibilityManager;
protected GlobalVariableManager globalVariableManager;
private final Consumer<CraftEngine> reloadEventDispatcher;
private boolean isReloading;
@@ -133,6 +135,7 @@ public abstract class CraftEngine implements Plugin {
this.translationManager.reload();
// clear the outdated cache by reloading the managers
this.templateManager.reload();
this.globalVariableManager.reload();
this.furnitureManager.reload();
this.fontManager.reload();
this.itemManager.reload();
@@ -198,6 +201,7 @@ public abstract class CraftEngine implements Plugin {
this.isInitializing = true;
this.networkManager.init();
this.templateManager = new TemplateManagerImpl();
this.globalVariableManager = new GlobalVariableManager();
this.itemBrowserManager = new ItemBrowserManagerImpl(this);
this.commandManager.registerDefaultFeatures();
// delay the reload so other plugins can register some custom parsers
@@ -245,6 +249,7 @@ public abstract class CraftEngine implements Plugin {
if (this.soundManager != null) this.soundManager.disable();
if (this.vanillaLootManager != null) this.vanillaLootManager.disable();
if (this.translationManager != null) this.translationManager.disable();
if (this.globalVariableManager != null) this.globalVariableManager.disable();
if (this.scheduler != null) this.scheduler.shutdownScheduler();
if (this.scheduler != null) this.scheduler.shutdownExecutor();
if (this.commandManager != null) this.commandManager.unregisterFeatures();
@@ -255,6 +260,8 @@ public abstract class CraftEngine implements Plugin {
protected void registerDefaultParsers() {
// register template parser
this.packManager.registerConfigSectionParser(this.templateManager.parser());
// register global variables parser
this.packManager.registerConfigSectionParser(this.globalVariableManager.parser());
// register font parser
this.packManager.registerConfigSectionParsers(this.fontManager.parsers());
// register item parser
@@ -430,6 +437,11 @@ public abstract class CraftEngine implements Plugin {
return compatibilityManager;
}
@Override
public GlobalVariableManager globalVariableManager() {
return globalVariableManager;
}
@Override
public Platform platform() {
return platform;

View File

@@ -12,6 +12,7 @@ import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender;
import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.template.TemplateManager;
import net.momirealms.craftengine.core.plugin.context.GlobalVariableManager;
import net.momirealms.craftengine.core.plugin.dependency.DependencyManager;
import net.momirealms.craftengine.core.plugin.gui.GuiManager;
import net.momirealms.craftengine.core.plugin.gui.category.ItemBrowserManager;
@@ -91,5 +92,7 @@ public interface Plugin {
CompatibilityManager compatibilityManager();
GlobalVariableManager globalVariableManager();
Platform platform();
}

View File

@@ -8,20 +8,25 @@ import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.util.Map;
public interface ConfigSectionParser extends Comparable<ConfigSectionParser> {
public interface ConfigParser extends Comparable<ConfigParser> {
String[] sectionId();
void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) throws LocalizedException;
default void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) throws LocalizedException {
this.parseObject(pack, path, id, section);
}
default void parseObject(Pack pack, Path path, Key id, Object object) throws LocalizedException {
}
int loadingSequence();
default boolean isTemplate() {
default boolean supportsParsingObject() {
return false;
}
@Override
default int compareTo(@NotNull ConfigSectionParser another) {
default int compareTo(@NotNull ConfigParser another) {
return Integer.compare(loadingSequence(), another.loadingSequence());
}
}

View File

@@ -1,11 +1,8 @@
package net.momirealms.craftengine.core.plugin.config.template;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import java.nio.file.Path;
import java.util.Map;
import java.util.regex.Pattern;
@@ -17,9 +14,7 @@ public interface TemplateManager extends Manageable {
String OVERRIDES = "overrides";
String ARGUMENTS = "arguments";
ConfigSectionParser parser();
void addTemplate(Pack pack, Path path, Key id, Object obj);
ConfigParser parser();
Map<String, Object> applyTemplates(Map<String, Object> input);
}

View File

@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.plugin.config.template;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.GsonHelper;
import net.momirealms.craftengine.core.util.Key;
@@ -24,7 +24,7 @@ public class TemplateManagerImpl implements TemplateManager {
this.templateParser = new TemplateParser();
}
public class TemplateParser implements ConfigSectionParser {
public class TemplateParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"templates", "template"};
@Override
@@ -38,13 +38,16 @@ public class TemplateManagerImpl implements TemplateManager {
}
@Override
public boolean isTemplate() {
public boolean supportsParsingObject() {
return true;
}
@Override
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
addTemplate(pack, path, id, section);
public void parseObject(Pack pack, Path path, Key id, Object obj) {
if (templates.containsKey(id)) {
throw new LocalizedResourceConfigException("warning.config.template.duplicate", path.toString(), id.toString());
}
templates.put(id, obj);
}
}
@@ -54,18 +57,10 @@ public class TemplateManagerImpl implements TemplateManager {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.templateParser;
}
@Override
public void addTemplate(Pack pack, Path path, Key id, Object obj) {
if (this.templates.containsKey(id)) {
throw new LocalizedResourceConfigException("warning.config.template.duplicate", path.toString(), id.toString());
}
this.templates.put(id, obj);
}
@Override
public Map<String, Object> applyTemplates(Map<String, Object> input) {
Objects.requireNonNull(input, "Input must not be null");

View File

@@ -24,7 +24,7 @@ public abstract class AbstractCommonContext implements Context {
public TagResolver[] tagResolvers() {
if (this.tagResolvers == null) {
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE, new I18NTag(this), new NamedArgumentTag(this),
new PlaceholderTag(null), new ExpressionTag(this)};
new PlaceholderTag(null), new ExpressionTag(this), new GlobalVariableTag(this)};
}
return this.tagResolvers;
}

View File

@@ -0,0 +1,57 @@
package net.momirealms.craftengine.core.plugin.context;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedException;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class GlobalVariableManager implements Manageable {
private final Map<String, String> globalVariables = new HashMap<>();
private final GlobalVariableParser parser = new GlobalVariableParser();
@Nullable
public String get(final String key) {
return this.globalVariables.get(key);
}
@Override
public void unload() {
this.globalVariables.clear();
}
public ConfigParser parser() {
return this.parser;
}
public class GlobalVariableParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"global-variables", "global-variable"};
@Override
public int loadingSequence() {
return LoadingSequence.GLOBAL_VAR;
}
@Override
public String[] sectionId() {
return CONFIG_SECTION_NAME;
}
@Override
public boolean supportsParsingObject() {
return true;
}
@Override
public void parseObject(Pack pack, Path path, net.momirealms.craftengine.core.util.Key id, Object object) throws LocalizedException {
if (object != null) {
globalVariables.put(id.value(), object.toString());
}
}
}
}

View File

@@ -48,11 +48,16 @@ public class PlayerOptionalContext extends AbstractAdditionalParameterContext im
return this.player;
}
public boolean isPlayerPresent() {
return this.player != null;
}
@Override
@NotNull
public TagResolver[] tagResolvers() {
if (this.tagResolvers == null) {
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE, new PlaceholderTag(this.player), new I18NTag(this), new NamedArgumentTag(this), new ExpressionTag(this)};
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE, new PlaceholderTag(this.player), new I18NTag(this),
new NamedArgumentTag(this), new ExpressionTag(this), new GlobalVariableTag(this)};
}
return this.tagResolvers;
}

View File

@@ -57,10 +57,18 @@ public class ViewerContext implements RelationalContext {
if (this.owner instanceof PlayerOptionalContext context) {
optionalOwner = context.player();
}
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE,
new PlaceholderTag(optionalOwner), new ViewerPlaceholderTag(this.viewer.player()),
new NamedArgumentTag(this.owner), new ViewerNamedArgumentTag(this.viewer),
new I18NTag(this), new ExpressionTag(this)};
if (optionalOwner != null && this.viewer.player != null) {
this.tagResolvers = new TagResolver[]{new RelationalPlaceholderTag(optionalOwner, this.viewer.player),
ShiftTag.INSTANCE, ImageTag.INSTANCE,
new PlaceholderTag(optionalOwner), new ViewerPlaceholderTag(this.viewer.player()),
new NamedArgumentTag(this.owner), new ViewerNamedArgumentTag(this.viewer),
new I18NTag(this), new ExpressionTag(this), new GlobalVariableTag(this)};
} else {
this.tagResolvers = new TagResolver[]{ShiftTag.INSTANCE, ImageTag.INSTANCE,
new PlaceholderTag(optionalOwner), new ViewerPlaceholderTag(this.viewer.player()),
new NamedArgumentTag(this.owner), new ViewerNamedArgumentTag(this.viewer),
new I18NTag(this), new ExpressionTag(this), new GlobalVariableTag(this)};
}
}
return this.tagResolvers;
}

View File

@@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.Recipe;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.gui.Gui;
import net.momirealms.craftengine.core.util.Key;
@@ -19,7 +19,7 @@ public interface ItemBrowserManager extends Manageable {
int MAX_RECIPE_DEPTH = 16;
String GET_ITEM_PERMISSION = "craftengine.browser.get_item";
ConfigSectionParser parser();
ConfigParser parser();
void addExternalCategoryMember(Key item, List<Key> category);

View File

@@ -8,7 +8,7 @@ import net.momirealms.craftengine.core.item.recipe.*;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.gui.*;
@@ -68,7 +68,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
}
@Override
public ConfigSectionParser parser() {
public ConfigParser parser() {
return this.categoryParser;
}
@@ -93,7 +93,7 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
return Optional.ofNullable(this.byId.get(key));
}
public class CategoryParser implements ConfigSectionParser {
public class CategoryParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"categories", "category"};
@Override

View File

@@ -3,7 +3,7 @@ package net.momirealms.craftengine.core.plugin.locale;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.translation.Translator;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -44,7 +44,7 @@ public interface TranslationManager extends Manageable {
return TranslationManagerImpl.instance;
}
ConfigSectionParser[] parsers();
ConfigParser[] parsers();
default String miniMessageTranslation(String key) {
return miniMessageTranslation(key, null);

View File

@@ -7,7 +7,7 @@ import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.Plugin;
import net.momirealms.craftengine.core.plugin.PluginProperties;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.config.StringKeyConstructor;
import net.momirealms.craftengine.core.plugin.text.minimessage.IndexedArgumentTag;
import net.momirealms.craftengine.core.util.AdventureHelper;
@@ -63,8 +63,8 @@ public class TranslationManagerImpl implements TranslationManager {
}
@Override
public ConfigSectionParser[] parsers() {
return new ConfigSectionParser[] {this.langParser, this.i18nParser};
public ConfigParser[] parsers() {
return new ConfigParser[] {this.langParser, this.i18nParser};
}
@Override
@@ -277,7 +277,7 @@ public class TranslationManagerImpl implements TranslationManager {
}
}
public class I18NParser implements ConfigSectionParser {
public class I18NParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"i18n", "internationalization", "translation", "translations"};
@Override
@@ -308,7 +308,7 @@ public class TranslationManagerImpl implements TranslationManager {
}
}
public class LangParser implements ConfigSectionParser {
public class LangParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"lang", "language", "languages"};
@Override

View File

@@ -0,0 +1,37 @@
package net.momirealms.craftengine.core.plugin.text.minimessage;
import net.kyori.adventure.text.minimessage.ParsingException;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.util.AdventureHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GlobalVariableTag implements TagResolver {
private final Context context;
public GlobalVariableTag(Context context) {
this.context = context;
}
@Override
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull net.kyori.adventure.text.minimessage.Context ctx) throws ParsingException {
if (!this.has(name)) {
return null;
}
String id = arguments.popOr("No argument variable id provided").toString();
String value = CraftEngine.instance().globalVariableManager().get(id);
if (value == null) {
throw ctx.newException("Unknown variable: ", arguments);
}
return Tag.selfClosingInserting(AdventureHelper.miniMessage().deserialize(value, this.context.tagResolvers()));
}
@Override
public boolean has(@NotNull String name) {
return "global".equals(name);
}
}

View File

@@ -0,0 +1,40 @@
package net.momirealms.craftengine.core.plugin.text.minimessage;
import net.kyori.adventure.text.minimessage.Context;
import net.kyori.adventure.text.minimessage.ParsingException;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.AdventureHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class RelationalPlaceholderTag implements TagResolver {
private final Player player1;
private final Player player2;
public RelationalPlaceholderTag(@NotNull Player player1, @NotNull Player player2) {
this.player1 = player1;
this.player2 = player2;
}
@Override
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull Context ctx) throws ParsingException {
if (!this.has(name) || !CraftEngine.instance().compatibilityManager().hasPlaceholderAPI()) {
return null;
}
String placeholder = "%" + arguments.popOr("No argument placeholder provided") + "%";
String parsed = CraftEngine.instance().compatibilityManager().parse(player1, player2, placeholder);
if (parsed.equals(placeholder)) {
parsed = arguments.popOr("No default papi value provided").toString();
}
return Tag.selfClosingInserting(AdventureHelper.miniMessage().deserialize(parsed));
}
@Override
public boolean has(@NotNull String name) {
return "rel_papi".equals(name);
}
}

View File

@@ -4,7 +4,7 @@ import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.*;
@@ -32,8 +32,8 @@ public abstract class AbstractSoundManager implements SoundManager {
}
@Override
public ConfigSectionParser[] parsers() {
return new ConfigSectionParser[] { this.soundParser, this.songParser };
public ConfigParser[] parsers() {
return new ConfigParser[] { this.soundParser, this.songParser };
}
@Override
@@ -59,7 +59,7 @@ public abstract class AbstractSoundManager implements SoundManager {
protected abstract void registerSongs(Map<Key, JukeboxSong> songs);
public class SongParser implements ConfigSectionParser {
public class SongParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"jukebox_songs", "song", "songs", "jukebox", "jukebox_song"};
@Override
@@ -86,7 +86,7 @@ public abstract class AbstractSoundManager implements SoundManager {
}
}
public class SoundParser implements ConfigSectionParser {
public class SoundParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"sounds", "sound"};
@Override

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.sound;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
import java.util.Map;
@@ -10,7 +10,7 @@ public interface SoundManager extends Manageable {
boolean isVanillaSoundEvent(Key key);
ConfigSectionParser[] parsers();
ConfigParser[] parsers();
Map<Key, SoundEvent> sounds();
}

View File

@@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G
# Project settings
# Rule: [major update].[feature update].[bug fix]
project_version=0.0.53.2
project_version=0.0.53.4
config_version=32
lang_version=12
project_group=net.momirealms