9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-23 17:09:19 +00:00

优化component实现

This commit is contained in:
XiaoMoMi
2025-04-14 02:27:57 +08:00
parent b63625ba20
commit b327ed11d5
24 changed files with 433 additions and 129 deletions

View File

@@ -118,7 +118,7 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
@Override
public ItemSettings settings() {
return settings;
return this.settings;
}
@Override

View File

@@ -89,26 +89,6 @@ public abstract class BukkitItemFactory extends ItemFactory<CraftEngine, RTagIte
return item.remove(path);
}
@Override
protected void setComponent(ItemWrapper<ItemStack> item, String type, Object value) {
item.setComponent(type, value);
}
@Override
protected Object getComponent(ItemWrapper<ItemStack> item, String type) {
return item.getComponent(type);
}
@Override
protected boolean hasComponent(ItemWrapper<ItemStack> item, String type) {
return item.hasComponent(type);
}
@Override
protected void removeComponent(ItemWrapper<ItemStack> item, String type) {
item.removeComponent(type);
}
@Override
protected void update(ItemWrapper<ItemStack> item) {
item.update();

View File

@@ -1,14 +1,18 @@
package net.momirealms.craftengine.bukkit.item.factory;
import com.google.gson.JsonElement;
import com.saicone.rtag.RtagItem;
import com.saicone.rtag.data.ComponentType;
import com.saicone.rtag.item.ItemObject;
import net.momirealms.craftengine.bukkit.item.RTagItemWrapper;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.EnchantmentUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Enchantment;
import net.momirealms.craftengine.core.item.ItemWrapper;
import net.momirealms.craftengine.core.item.Trim;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.inventory.ItemStack;
@@ -26,17 +30,59 @@ public class ComponentItemFactory extends BukkitItemFactory {
super(plugin);
}
@Override
protected void setComponent(ItemWrapper<ItemStack> item, Key type, Object value) {
if (value instanceof JsonElement jsonElement) {
setJsonComponentDirectly(item, type, jsonElement);
} else {
setJavaComponentDirectly(item, type, value);
}
}
@Override
protected void resetComponent(ItemWrapper<ItemStack> item, Key type) {
FastNMS.INSTANCE.resetComponent(item.getLiteralObject(), KeyUtils.toResourceLocation(type));
}
@Override
protected Object getComponent(ItemWrapper<ItemStack> item, Key type) {
return item.getComponent(type);
}
@Override
protected boolean hasComponent(ItemWrapper<ItemStack> item, Key type) {
return item.hasComponent(type);
}
@Override
protected void removeComponent(ItemWrapper<ItemStack> item, Key type) {
FastNMS.INSTANCE.removeComponent(item.getLiteralObject(), KeyUtils.toResourceLocation(type));
}
protected void setJavaComponentDirectly(ItemWrapper<ItemStack> item, Key type, Object value) {
ComponentType.parseJava(type, value).ifPresent(it -> FastNMS.INSTANCE.setComponent(item.getLiteralObject(), KeyUtils.toResourceLocation(type), it));
}
protected void setJsonComponentDirectly(ItemWrapper<ItemStack> item, Key type, JsonElement value) {
ComponentType.parseJson(type, value).ifPresent(it -> FastNMS.INSTANCE.setComponent(item.getLiteralObject(), KeyUtils.toResourceLocation(type), it));
}
@Override
public Object encodeJava(Key componentType, @Nullable Object component) {
return ComponentType.encodeJava(componentType, component).orElse(null);
}
@Override
protected JsonElement encodeJson(Key type, Object component) {
return ComponentType.encodeJson(type, component).orElse(null);
}
@Override
protected void customModelData(ItemWrapper<ItemStack> item, Integer data) {
if (data == null) {
item.removeComponent(ComponentKeys.CUSTOM_MODEL_DATA);
resetComponent(item, ComponentKeys.CUSTOM_MODEL_DATA);
} else {
item.setComponent(ComponentKeys.CUSTOM_MODEL_DATA, data);
setJavaComponentDirectly(item, ComponentKeys.CUSTOM_MODEL_DATA, data);
}
}
@@ -53,9 +99,9 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void customName(ItemWrapper<ItemStack> item, String json) {
if (json == null) {
item.removeComponent(ComponentKeys.CUSTOM_NAME);
resetComponent(item, ComponentKeys.CUSTOM_NAME);
} else {
item.setComponent(ComponentKeys.CUSTOM_NAME, json);
setJavaComponentDirectly(item, ComponentKeys.CUSTOM_NAME, json);
}
}
@@ -73,9 +119,9 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void itemName(ItemWrapper<ItemStack> item, String json) {
if (json == null) {
item.removeComponent(ComponentKeys.ITEM_NAME);
resetComponent(item, ComponentKeys.ITEM_NAME);
} else {
item.setComponent(ComponentKeys.ITEM_NAME, json);
setJavaComponentDirectly(item, ComponentKeys.ITEM_NAME, json);
}
}
@@ -92,15 +138,12 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void skull(ItemWrapper<ItemStack> item, String skullData) {
final Map<String, Object> profile = Map.of(
"properties", List.of(
Map.of(
"name", "textures",
"value", skullData
)
)
);
item.setComponent("minecraft:profile", profile);
if (skullData == null) {
resetComponent(item, ComponentKeys.PROFILE);
} else {
Map<String, Object> profile = Map.of("properties", List.of(Map.of("name", "textures", "value", skullData)));
setJavaComponentDirectly(item, ComponentKeys.PROFILE, profile);
}
}
@SuppressWarnings("unchecked")
@@ -118,9 +161,9 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void lore(ItemWrapper<ItemStack> item, List<String> lore) {
if (lore == null || lore.isEmpty()) {
item.removeComponent(ComponentKeys.LORE);
resetComponent(item, ComponentKeys.LORE);
} else {
item.setComponent(ComponentKeys.LORE, lore);
setJavaComponentDirectly(item, ComponentKeys.LORE, lore);
}
}
@@ -132,9 +175,9 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void unbreakable(ItemWrapper<ItemStack> item, boolean unbreakable) {
if (unbreakable) {
item.removeComponent(ComponentKeys.UNBREAKABLE);
resetComponent(item, ComponentKeys.UNBREAKABLE);
} else {
item.setComponent(ComponentKeys.UNBREAKABLE, true);
setJavaComponentDirectly(item, ComponentKeys.UNBREAKABLE, true);
}
}
@@ -145,7 +188,11 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void glint(ItemWrapper<ItemStack> item, Boolean glint) {
item.setComponent(ComponentKeys.ENCHANTMENT_GLINT_OVERRIDE, glint);
if (glint == null) {
resetComponent(item, ComponentKeys.ENCHANTMENT_GLINT_OVERRIDE);
} else {
setJavaComponentDirectly(item, ComponentKeys.ENCHANTMENT_GLINT_OVERRIDE, glint);
}
}
@Override
@@ -161,8 +208,11 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void damage(ItemWrapper<ItemStack> item, Integer damage) {
if (damage == null) damage = 0;
item.setComponent(ComponentKeys.DAMAGE, damage);
if (damage == null) {
resetComponent(item, ComponentKeys.DAMAGE);
} else {
setJavaComponentDirectly(item, ComponentKeys.DAMAGE, damage);
}
}
@Override
@@ -179,9 +229,9 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void maxDamage(ItemWrapper<ItemStack> item, Integer damage) {
if (damage == null) {
item.removeComponent(ComponentKeys.MAX_DAMAGE);
resetComponent(item, ComponentKeys.MAX_DAMAGE);
} else {
item.setComponent(ComponentKeys.MAX_DAMAGE, damage);
setJavaComponentDirectly(item, ComponentKeys.MAX_DAMAGE, damage);
}
}
@@ -202,27 +252,27 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void enchantments(ItemWrapper<ItemStack> item, List<Enchantment> enchantments) {
if (enchantments == null || enchantments.isEmpty()) {
item.removeComponent(ComponentKeys.ENCHANTMENTS);
return;
}
resetComponent(item, ComponentKeys.ENCHANTMENTS);
} else {
Map<String, Integer> enchants = new HashMap<>();
for (Enchantment enchantment : enchantments) {
enchants.put(enchantment.id().toString(), enchantment.level());
}
item.setComponent(ComponentKeys.ENCHANTMENTS, enchants);
setJavaComponentDirectly(item, ComponentKeys.ENCHANTMENTS, enchants);
}
}
@Override
protected void storedEnchantments(ItemWrapper<ItemStack> item, List<Enchantment> enchantments) {
if (enchantments == null || enchantments.isEmpty()) {
item.removeComponent(ComponentKeys.STORED_ENCHANTMENTS);
return;
}
resetComponent(item, ComponentKeys.STORED_ENCHANTMENTS);
} else {
Map<String, Integer> enchants = new HashMap<>();
for (Enchantment enchantment : enchantments) {
enchants.put(enchantment.id().toString(), enchantment.level());
}
item.setComponent(ComponentKeys.STORED_ENCHANTMENTS, enchants);
setJavaComponentDirectly(item, ComponentKeys.STORED_ENCHANTMENTS, enchants);
}
}
@Override
@@ -231,7 +281,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
try {
Map<String, Integer> map = EnchantmentUtils.toMap(enchant);
map.put(enchantment.toString(), enchantment.level());
item.setComponent(ComponentKeys.ENCHANTMENTS, map);
setJavaComponentDirectly(item, ComponentKeys.ENCHANTMENTS, map);
} catch (ReflectiveOperationException e) {
plugin.logger().warn("Failed to add enchantment", e);
}
@@ -243,7 +293,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
try {
Map<String, Integer> map = EnchantmentUtils.toMap(enchant);
map.put(enchantment.toString(), enchantment.level());
item.setComponent(ComponentKeys.STORED_ENCHANTMENTS, map);
setJavaComponentDirectly(item, ComponentKeys.STORED_ENCHANTMENTS, map);
} catch (ReflectiveOperationException e) {
plugin.logger().warn("Failed to add stored enchantment", e);
}
@@ -264,18 +314,18 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void maxStackSize(ItemWrapper<ItemStack> item, Integer maxStackSize) {
if (maxStackSize == null) {
item.removeComponent(ComponentKeys.MAX_STACK_SIZE);
resetComponent(item, ComponentKeys.MAX_STACK_SIZE);
} else {
item.setComponent(ComponentKeys.MAX_STACK_SIZE, maxStackSize);
setJavaComponentDirectly(item, ComponentKeys.MAX_STACK_SIZE, maxStackSize);
}
}
@Override
protected void repairCost(ItemWrapper<ItemStack> item, Integer data) {
if (data == null) {
item.removeComponent(ComponentKeys.REPAIR_COST);
resetComponent(item, ComponentKeys.REPAIR_COST);
} else {
item.setComponent(ComponentKeys.REPAIR_COST, data);
setJavaComponentDirectly(item, ComponentKeys.REPAIR_COST, data);
}
}
@@ -302,7 +352,6 @@ public class ComponentItemFactory extends BukkitItemFactory {
@Override
protected void merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
// load previous changes on nms items
item1.load();
Object itemStack1 = item1.getLiteralObject();
Object itemStack2 = item2.getLiteralObject();
try {
@@ -311,4 +360,28 @@ public class ComponentItemFactory extends BukkitItemFactory {
plugin.logger().warn("Failed to merge item", e);
}
}
@Override
protected void trim(ItemWrapper<ItemStack> item, Trim trim) {
if (trim == null) {
resetComponent(item, ComponentKeys.TRIM);
} else {
setJavaComponentDirectly(item, ComponentKeys.TRIM, Map.of(
"pattern", trim.pattern(),
"material", trim.material()
));
}
}
@Override
protected Optional<Trim> trim(ItemWrapper<ItemStack> item) {
if (!item.hasComponent(ComponentKeys.TRIM)) return Optional.empty();
Optional<Object> trim = ComponentType.encodeJava(ComponentKeys.TRIM, item.getComponent(ComponentKeys.TRIM));
if (trim.isEmpty()) {
return Optional.empty();
}
@SuppressWarnings("unchecked")
Map<String, String> trimMap = (Map<String, String>) trim.get();
return Optional.of(new Trim(trimMap.get("pattern"), trimMap.get("material")));
}
}

View File

@@ -33,9 +33,9 @@ public class ComponentItemFactory1_21_4 extends ComponentItemFactory {
@Override
protected void customModelData(ItemWrapper<ItemStack> item, Integer data) {
if (data == null) {
item.removeComponent(ComponentKeys.CUSTOM_MODEL_DATA);
resetComponent(item, ComponentKeys.CUSTOM_MODEL_DATA);
} else {
item.setComponent(ComponentKeys.CUSTOM_MODEL_DATA, Map.of("floats", List.of(data.floatValue())));
setComponent(item, ComponentKeys.CUSTOM_MODEL_DATA, Map.of("floats", List.of(data.floatValue())));
}
}
}

View File

@@ -26,9 +26,9 @@ public class ComponentItemFactory1_21_5 extends ComponentItemFactory1_21_4 {
@Override
protected void customName(ItemWrapper<ItemStack> item, String json) {
if (json == null) {
item.removeComponent(ComponentKeys.CUSTOM_NAME);
resetComponent(item, ComponentKeys.CUSTOM_NAME);
} else {
item.setComponent(ComponentKeys.CUSTOM_NAME, ChatComponent.toTag(ComponentUtils.jsonToMinecraft(json)));
setJavaComponentDirectly(item, ComponentKeys.CUSTOM_NAME, ChatComponent.toTag(ComponentUtils.jsonToMinecraft(json)));
}
}
@@ -41,9 +41,9 @@ public class ComponentItemFactory1_21_5 extends ComponentItemFactory1_21_4 {
@Override
protected void itemName(ItemWrapper<ItemStack> item, String json) {
if (json == null) {
item.removeComponent(ComponentKeys.ITEM_NAME);
resetComponent(item, ComponentKeys.ITEM_NAME);
} else {
item.setComponent(ComponentKeys.ITEM_NAME, ChatComponent.toTag(ComponentUtils.jsonToMinecraft(json)));
setJavaComponentDirectly(item, ComponentKeys.ITEM_NAME, ChatComponent.toTag(ComponentUtils.jsonToMinecraft(json)));
}
}
@@ -71,13 +71,13 @@ public class ComponentItemFactory1_21_5 extends ComponentItemFactory1_21_4 {
@Override
protected void lore(ItemWrapper<ItemStack> item, List<String> lore) {
if (lore == null || lore.isEmpty()) {
item.removeComponent(ComponentKeys.LORE);
resetComponent(item, ComponentKeys.LORE);
} else {
List<Object> loreTags = new ArrayList<>();
for (String json : lore) {
loreTags.add(ChatComponent.toTag(ComponentUtils.jsonToMinecraft(json)));
}
item.setComponent(ComponentKeys.LORE, TagList.newTag(loreTags));
setJavaComponentDirectly(item, ComponentKeys.LORE, TagList.newTag(loreTags));
}
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.bukkit.item.factory;
import com.google.gson.JsonElement;
import com.saicone.rtag.RtagItem;
import com.saicone.rtag.item.ItemObject;
import com.saicone.rtag.tag.TagBase;
@@ -8,6 +9,7 @@ import com.saicone.rtag.tag.TagList;
import net.momirealms.craftengine.bukkit.item.RTagItemWrapper;
import net.momirealms.craftengine.core.item.Enchantment;
import net.momirealms.craftengine.core.item.ItemWrapper;
import net.momirealms.craftengine.core.item.Trim;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.SkullUtils;
@@ -26,6 +28,36 @@ public class UniversalItemFactory extends BukkitItemFactory {
super(plugin);
}
@Override
protected void resetComponent(ItemWrapper<ItemStack> item, Key type) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
}
@Override
protected JsonElement encodeJson(Key type, Object component) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
}
@Override
protected void setComponent(ItemWrapper<ItemStack> item, Key type, Object value) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
}
@Override
protected Object getComponent(ItemWrapper<ItemStack> item, Key type) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
}
@Override
protected boolean hasComponent(ItemWrapper<ItemStack> item, Key type) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
}
@Override
protected void removeComponent(ItemWrapper<ItemStack> item, Key type) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
}
@Override
public Object encodeJava(Key componentType, @Nullable Object component) {
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
@@ -256,4 +288,22 @@ public class UniversalItemFactory extends BukkitItemFactory {
item1.load();
TagCompound.merge(ItemObject.getCustomDataTag(item1.getLiteralObject()), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
}
@Override
protected void trim(ItemWrapper<ItemStack> item, Trim trim) {
if (trim == null) {
item.remove("Trim");
return;
}
item.set(trim.material(), "Trim", "material");
item.set(trim.pattern(), "Trim", "pattern");
}
@Override
protected Optional<Trim> trim(ItemWrapper<ItemStack> item) {
String material = item.get("Trim", "material");
String pattern = item.get("Trim", "pattern");
if (material == null || pattern == null) return Optional.empty();
return Optional.of(new Trim(material, pattern));
}
}

View File

@@ -28,7 +28,8 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
ItemStack itemStack = new ItemStack(Material.STONE);
RtagItem rtagItem = new RtagItem(itemStack);
rtagItem.setComponent(ComponentKeys.CUSTOM_DATA, Map.of("test1", "1"));
rtagItem.setComponent(ComponentKeys.CUSTOM_DATA, Map.of("test2", "2"));
rtagItem.removeComponent(ComponentKeys.CUSTOM_DATA);
rtagItem.removeComponent(ComponentKeys.LORE);
player.getInventory().addItem(rtagItem.load());
});
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.item;
import com.google.gson.JsonElement;
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
import net.momirealms.craftengine.core.util.Key;
@@ -95,6 +96,17 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
return this;
}
@Override
public Item<I> trim(Trim trim) {
this.factory.trim(this.item, trim);
return this;
}
@Override
public Optional<Trim> trim() {
return this.factory.trim(this.item);
}
@Override
public Item<I> customModelData(Integer data) {
this.factory.customModelData(this.item, data);
@@ -224,25 +236,40 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
}
@Override
public boolean hasComponent(String type) {
public boolean hasComponent(Key type) {
return this.factory.hasComponent(this.item, type);
}
@Override
public void removeComponent(String type) {
public void removeComponent(Key type) {
this.factory.removeComponent(this.item, type);
}
@Override
public Object getComponent(String type) {
public Object getComponent(Key type) {
return this.factory.getComponent(this.item, type);
}
@Override
public void setComponent(String type, Object value) {
public Object getJavaTypeComponent(Key type) {
return this.factory.encodeJava(type, getComponent(type));
}
@Override
public JsonElement getJsonTypeComponent(Key type) {
return this.factory.encodeJson(type, getComponent(type));
}
@Override
public void setComponent(Key type, Object value) {
this.factory.setComponent(this.item, type, value);
}
@Override
public void resetComponent(Key type) {
this.factory.resetComponent(this.item, type);
}
@Override
public I getItem() {
return this.factory.getItem(this.item);

View File

@@ -3,22 +3,23 @@ package net.momirealms.craftengine.core.item;
import net.momirealms.craftengine.core.util.Key;
public class ComponentKeys {
public static final String CUSTOM_MODEL_DATA = Key.of("minecraft", "custom_model_data").toString();
public static final String CUSTOM_NAME = Key.of("minecraft", "custom_name").toString();
public static final String ITEM_NAME = Key.of("minecraft", "item_name").toString();
public static final String LORE = Key.of("minecraft", "lore").toString();
public static final String DAMAGE = Key.of("minecraft", "damage").toString();
public static final String MAX_DAMAGE = Key.of("minecraft", "max_damage").toString();
public static final String ENCHANTMENT_GLINT_OVERRIDE = Key.of("minecraft", "enchantment_glint_override").toString();
public static final String ENCHANTMENTS = Key.of("minecraft", "enchantments").toString();
public static final String STORED_ENCHANTMENTS = Key.of("minecraft", "stored_enchantments").toString();
public static final String UNBREAKABLE = Key.of("minecraft", "unbreakable").toString();
public static final String MAX_STACK_SIZE = Key.of("minecraft", "max_stack_size").toString();
public static final String EQUIPPABLE = Key.of("minecraft", "equippable").toString();
public static final String ITEM_MODEL = Key.of("minecraft", "item_model").toString();
public static final String TOOLTIP_STYLE = Key.of("minecraft", "tooltip_style").toString();
public static final String JUKEBOX_PLAYABLE = Key.of("minecraft", "jukebox_playable").toString();
public static final String TRIM = Key.of("minecraft", "trim").toString();
public static final String REPAIR_COST = Key.of("minecraft", "repair_cost").toString();
public static final String CUSTOM_DATA = Key.of("minecraft", "custom_data").toString();
public static final Key CUSTOM_MODEL_DATA = Key.of("minecraft", "custom_model_data");
public static final Key CUSTOM_NAME = Key.of("minecraft", "custom_name");
public static final Key ITEM_NAME = Key.of("minecraft", "item_name");
public static final Key LORE = Key.of("minecraft", "lore");
public static final Key DAMAGE = Key.of("minecraft", "damage");
public static final Key MAX_DAMAGE = Key.of("minecraft", "max_damage");
public static final Key ENCHANTMENT_GLINT_OVERRIDE = Key.of("minecraft", "enchantment_glint_override");
public static final Key ENCHANTMENTS = Key.of("minecraft", "enchantments");
public static final Key STORED_ENCHANTMENTS = Key.of("minecraft", "stored_enchantments");
public static final Key UNBREAKABLE = Key.of("minecraft", "unbreakable");
public static final Key MAX_STACK_SIZE = Key.of("minecraft", "max_stack_size");
public static final Key EQUIPPABLE = Key.of("minecraft", "equippable");
public static final Key ITEM_MODEL = Key.of("minecraft", "item_model");
public static final Key TOOLTIP_STYLE = Key.of("minecraft", "tooltip_style");
public static final Key JUKEBOX_PLAYABLE = Key.of("minecraft", "jukebox_playable");
public static final Key TRIM = Key.of("minecraft", "trim");
public static final Key REPAIR_COST = Key.of("minecraft", "repair_cost");
public static final Key CUSTOM_DATA = Key.of("minecraft", "custom_data");
public static final Key PROFILE = Key.of("minecraft", "profile");
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.item;
import com.google.gson.JsonElement;
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
import net.momirealms.craftengine.core.util.Key;
@@ -33,6 +34,10 @@ public interface Item<I> {
Item<I> count(int amount);
Item<I> trim(Trim trim);
Optional<Trim> trim();
Item<I> customModelData(Integer data);
Optional<Integer> customModelData();
@@ -91,13 +96,19 @@ public interface Item<I> {
boolean removeTag(Object... path);
boolean hasComponent(String type);
boolean hasComponent(Key type);
void removeComponent(String type);
void removeComponent(Key type);
Object getComponent(String type);
Object getComponent(Key type);
void setComponent(String type, Object value);
Object getJavaTypeComponent(Key type);
JsonElement getJsonTypeComponent(Key type);
void setComponent(Key type, Object value);
void resetComponent(Key type);
I getItem();

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.item;
import com.google.gson.JsonElement;
import net.momirealms.craftengine.core.plugin.Plugin;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.Nullable;
@@ -22,6 +23,8 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
public abstract Object encodeJava(Key componentType, @Nullable Object component);
protected abstract JsonElement encodeJson(Key type, Object component);
protected abstract ItemWrapper<I> wrapInternal(I item);
protected abstract Object getTag(ItemWrapper<I> item, Object... path);
@@ -32,13 +35,15 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
protected abstract boolean removeTag(ItemWrapper<I> item, Object... path);
protected abstract void setComponent(ItemWrapper<I> item, String type, Object value);
protected abstract void setComponent(ItemWrapper<I> item, Key type, Object value);
protected abstract Object getComponent(ItemWrapper<I> item, String type);
protected abstract Object getComponent(ItemWrapper<I> item, Key type);
protected abstract boolean hasComponent(ItemWrapper<I> item, String type);
protected abstract boolean hasComponent(ItemWrapper<I> item, Key type);
protected abstract void removeComponent(ItemWrapper<I> item, String type);
protected abstract void removeComponent(ItemWrapper<I> item, Key type);
protected abstract void resetComponent(ItemWrapper<I> item, Key type);
protected abstract void update(ItemWrapper<I> item);
@@ -112,6 +117,10 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
protected abstract Optional<Integer> repairCost(ItemWrapper<I> item);
protected abstract void trim(ItemWrapper<I> item, Trim trim);
protected abstract Optional<Trim> trim(ItemWrapper<I> item);
protected abstract ItemWrapper<I> mergeCopy(ItemWrapper<I> item1, ItemWrapper<I> item2);
protected abstract void merge(ItemWrapper<I> item1, ItemWrapper<I> item2);

View File

@@ -0,0 +1,4 @@
package net.momirealms.craftengine.core.item;
public record Trim(String pattern, String material) {
}

View File

@@ -1,7 +1,12 @@
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;
import net.momirealms.craftengine.core.util.GsonHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.Pair;
import java.util.ArrayList;
@@ -9,16 +14,42 @@ import java.util.List;
import java.util.Map;
public class ComponentModifier<I> implements ItemDataModifier<I> {
private final List<Pair<String, Object>> arguments;
private final List<Pair<Key, Object>> arguments;
private JsonObject customData = null;
public ComponentModifier(Map<String, Object> arguments) {
List<Pair<String, Object>> pairs = new ArrayList<>(arguments.size());
List<Pair<Key, Object>> pairs = new ArrayList<>(arguments.size());
for (Map.Entry<String, Object> entry : arguments.entrySet()) {
pairs.add(new Pair<>(entry.getKey(), entry.getValue()));
Key key = Key.of(entry.getKey());
if (key.equals(ComponentKeys.CUSTOM_DATA)) {
this.customData = parseJsonObjectValue(entry.getValue());
} else {
pairs.add(new Pair<>(key, parseValue(entry.getValue())));
}
}
this.arguments = pairs;
}
private Object parseValue(Object value) {
if (value instanceof String string) {
if (string.startsWith("(json) ")) {
return GsonHelper.get().fromJson(string.substring("(json) ".length()), JsonElement.class);
}
}
return value;
}
private JsonObject parseJsonObjectValue(Object value) {
if (value instanceof String string) {
if (string.startsWith("(json) ")) {
return GsonHelper.get().fromJson(string.substring("(json) ".length()), JsonObject.class);
}
} else if (value instanceof Map<?,?> map) {
return (JsonObject) GsonHelper.get().toJsonTree(map, Map.class);
}
throw new UnsupportedOperationException("Invalid minecraft:custom_data value: " + value.toString());
}
@Override
public String name() {
return "components";
@@ -26,15 +57,33 @@ public class ComponentModifier<I> implements ItemDataModifier<I> {
@Override
public void apply(Item<I> item, ItemBuildContext context) {
for (Pair<String, Object> entry : this.arguments) {
for (Pair<Key, Object> entry : this.arguments) {
item.setComponent(entry.left(), entry.right());
}
if (this.customData != null) {
JsonObject tag = (JsonObject) item.getJsonTypeComponent(ComponentKeys.CUSTOM_DATA);
if (tag != null) {
item.setComponent(ComponentKeys.CUSTOM_DATA, GsonHelper.shallowMerge(this.customData, tag));
} else {
item.setComponent(ComponentKeys.CUSTOM_DATA, this.customData);
}
}
}
@Override
public void remove(Item<I> item) {
for (Pair<String, Object> entry : this.arguments) {
item.removeComponent(entry.left());
for (Pair<Key, Object> entry : this.arguments) {
item.resetComponent(entry.left());
}
if (this.customData != null) {
JsonObject tag = (JsonObject) item.getJsonTypeComponent(ComponentKeys.CUSTOM_DATA);
if (tag != null) {
// crude method
for (String key : this.customData.keySet()) {
tag.remove(key);
}
item.setComponent(ComponentKeys.CUSTOM_DATA, tag);
}
}
}
}

View File

@@ -1,8 +1,12 @@
package net.momirealms.craftengine.core.item.modifier;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
import java.util.Map;
public class IdModifier<I> implements ItemDataModifier<I> {
public static final String CRAFT_ENGINE_ID = "craftengine:id";
@@ -19,8 +23,12 @@ public class IdModifier<I> implements ItemDataModifier<I> {
@Override
public void apply(Item<I> item, ItemBuildContext context) {
if (VersionHelper.isVersionNewerThan1_20_5()) {
item.setComponent(ComponentKeys.CUSTOM_DATA, Map.of(CRAFT_ENGINE_ID, argument.toString()));
} else {
item.setTag(argument.toString(), CRAFT_ENGINE_ID);
}
}
@Override
public void remove(Item<I> item) {

View File

@@ -3,10 +3,9 @@ package net.momirealms.craftengine.core.item.modifier;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.Trim;
import net.momirealms.craftengine.core.util.VersionHelper;
import java.util.Map;
public class TrimModifier<I> implements ItemDataModifier<I> {
private final String material;
private final String pattern;
@@ -23,19 +22,18 @@ public class TrimModifier<I> implements ItemDataModifier<I> {
@Override
public void apply(Item<I> item, ItemBuildContext context) {
item.trim(new Trim(this.material, this.pattern));
if (VersionHelper.isVersionNewerThan1_20_5()) {
item.setComponent(ComponentKeys.TRIM, Map.of(
"pattern", this.pattern,
"material", this.material
));
} else {
item.setTag(this.material, "Trim", "material");
item.setTag(this.pattern, "Trim", "pattern");
}
}
@Override
public void remove(Item<I> item) {
item.trim(null);
if (VersionHelper.isVersionNewerThan1_20_5()) {
item.removeComponent(ComponentKeys.TRIM);
} else {

View File

@@ -217,9 +217,9 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
@Override
public void accept(Item<?> item1, Item<?> item2, Item<?> item3) {
for (Key component : this.components) {
Object componentObj = item1.getComponent(component.toString());
Object componentObj = item1.getComponent(component);
if (componentObj != null) {
item3.setComponent(component.toString(), CraftEngine.instance().itemManager().encodeJava(component, componentObj));
item3.setComponent(component, componentObj);
}
}
}

View File

@@ -233,7 +233,6 @@ public abstract class AbstractPackManager implements PackManager {
Files.createDirectories(resourcesFolder);
this.saveDefaultConfigs();
}
try (DirectoryStream<Path> paths = Files.newDirectoryStream(resourcesFolder)) {
for (Path path : paths) {
if (!Files.isDirectory(path)) {
@@ -247,6 +246,9 @@ public abstract class AbstractPackManager implements PackManager {
String author = null;
if (Files.exists(metaFile) && Files.isRegularFile(metaFile)) {
YamlDocument metaYML = Config.instance().loadYamlData(metaFile.toFile());
if (!metaYML.getBoolean("enable", true)) {
continue;
}
namespace = metaYML.getString("namespace", namespace);
description = metaYML.getString("description");
version = metaYML.getString("version");

View File

@@ -51,7 +51,7 @@ byte_buddy_version=1.17.5
ahocorasick_version=0.6.3
snake_yaml_version=2.4
anti_grief_version=0.13
nms_helper_version=0.57
nms_helper_version=0.57.3
# Ignite Dependencies
mixinextras_version=0.4.1
mixin_version=0.15.2+mixin.0.8.7

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.mod;
package net.momirealms.craftengine.mod.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -14,6 +14,7 @@ import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.momirealms.craftengine.mod.CraftEnginePlugin;
import net.momirealms.craftengine.mod.util.NoteBlockUtils;
import net.momirealms.craftengine.shared.ObjectHolder;
import net.momirealms.craftengine.shared.block.*;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.mod;
package net.momirealms.craftengine.mod.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;

View File

@@ -0,0 +1,41 @@
package net.momirealms.craftengine.mod.item;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.function.Function;
public class CustomStreamCodec implements StreamCodec<RegistryFriendlyByteBuf, ItemStack> {
public static Function<ItemStack, ItemStack> clientBoundDataProcessor;
public static Function<ItemStack, ItemStack> serverBoundDataProcessor;
private final StreamCodec<RegistryFriendlyByteBuf, ItemStack> original;
public CustomStreamCodec(StreamCodec<RegistryFriendlyByteBuf, ItemStack> original) {
this.original = Objects.requireNonNull(original);
}
@Override
public @NotNull ItemStack decode(@NotNull RegistryFriendlyByteBuf buffer) {
ItemStack itemStack = this.original.decode(buffer);
if (!itemStack.isEmpty()) {
if (serverBoundDataProcessor != null) {
itemStack = serverBoundDataProcessor.apply(itemStack);
}
}
return itemStack;
}
@Override
public void encode(@NotNull RegistryFriendlyByteBuf buffer, @NotNull ItemStack value) {
if (!value.isEmpty()) {
if (clientBoundDataProcessor != null) {
value = clientBoundDataProcessor.apply(value);
}
}
this.original.encode(buffer, value);
}
}

View File

@@ -11,8 +11,8 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.momirealms.craftengine.mod.CraftEngineBlock;
import net.momirealms.craftengine.mod.CraftEnginePlugin;
import net.momirealms.craftengine.mod.block.CraftEngineBlock;
import net.momirealms.craftengine.mod.util.NoteBlockUtils;
import org.bukkit.configuration.file.YamlConfiguration;
import org.spongepowered.asm.mixin.Mixin;
@@ -27,7 +27,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
@Mixin(value = Blocks.class)
public abstract class MixinBlocks {
public abstract class BlocksMixin {
@Inject(method = "<clinit>", at = @At("RETURN"))
private static void onBlocksInit(CallbackInfo ci) {

View File

@@ -0,0 +1,48 @@
package net.momirealms.craftengine.mod.mixin;
import net.minecraft.core.NonNullList;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.item.ItemStack;
import net.momirealms.craftengine.mod.item.CustomStreamCodec;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(ItemStack.class)
public abstract class ItemStackMixin {
@Shadow(remap = false)
@Mutable
public static StreamCodec<RegistryFriendlyByteBuf, ItemStack> OPTIONAL_STREAM_CODEC;
@Shadow(remap = false)
@Mutable
public static StreamCodec<RegistryFriendlyByteBuf, List<ItemStack>> OPTIONAL_LIST_STREAM_CODEC;
private static StreamCodec<RegistryFriendlyByteBuf, ItemStack> ORIGINAL_OPTIONAL_STREAM_CODEC;
@Inject(
method = "<clinit>",
at = @At(
value = "FIELD",
target = "Lnet/minecraft/world/item/ItemStack;OPTIONAL_STREAM_CODEC:Lnet/minecraft/network/codec/StreamCodec;",
opcode = Opcodes.PUTSTATIC,
shift = At.Shift.AFTER
)
)
private static void captureOriginalAfterAssignment(CallbackInfo ci) {
ORIGINAL_OPTIONAL_STREAM_CODEC = OPTIONAL_STREAM_CODEC;
}
@Inject(method = "<clinit>", at = @At("RETURN"))
private static void replaceStreamCodec(CallbackInfo ci) {
OPTIONAL_STREAM_CODEC = new CustomStreamCodec(ORIGINAL_OPTIONAL_STREAM_CODEC);
OPTIONAL_LIST_STREAM_CODEC = OPTIONAL_STREAM_CODEC.apply(ByteBufCodecs.collection(NonNullList::createWithCapacity));
}
}

View File

@@ -6,6 +6,7 @@
"target": "@env(DEFAULT)",
"compatibilityLevel": "JAVA_21",
"server": [
"MixinBlocks"
"BlocksMixin",
"ItemStackMixin"
]
}