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

framework for external items

This commit is contained in:
XiaoMoMi
2025-03-22 21:13:17 +08:00
parent 951a9c321e
commit 2e6eddf17a
20 changed files with 170 additions and 13 deletions

View File

@@ -18,6 +18,7 @@ dependencies {
implementation(project(":core"))
implementation(project(":bukkit"))
implementation(project(":bukkit:legacy"))
implementation(project(":bukkit:compatibility"))
implementation("net.kyori:adventure-platform-bukkit:${rootProject.properties["adventure_platform_version"]}")
implementation("com.saicone.rtag:rtag-item:${rootProject.properties["rtag_version"]}")

View File

@@ -15,6 +15,7 @@ repositories {
dependencies {
compileOnly(project(":core"))
compileOnly(project(":shared"))
compileOnly(project(":bukkit:compatibility"))
compileOnly(project(":bukkit:legacy"))
// Anti Grief
compileOnly("com.github.Xiao-MoMi:AntiGriefLib:${rootProject.properties["anti_grief_version"]}")

View File

@@ -0,0 +1,28 @@
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://r.irepo.space/maven/")
}
dependencies {
compileOnly(project(":core"))
// Platform
compileOnly("dev.folia:folia-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
// NeigeItems
compileOnly("pers.neige.neigeitems:NeigeItems:1.21.42")
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
withSourcesJar()
}
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
options.release.set(21)
dependsOn(tasks.clean)
}

View File

@@ -0,0 +1,22 @@
package net.momirealms.craftengine.bukkit.compatibility.item;
import net.momirealms.craftengine.core.item.ExternalItemProvider;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import pers.neige.neigeitems.manager.ItemManager;
import java.util.Optional;
public class NeigeItemsProvider implements ExternalItemProvider<ItemStack> {
@Override
public String plugin() {
return "NeigeItems";
}
@Override
public ItemStack build(String id, ItemBuildContext context) {
return ItemManager.INSTANCE.getItemStack(id, Optional.ofNullable(context.player()).map(it -> (Player) it.platformPlayer()).orElse(null));
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.bukkit.item;
import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider;
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
import net.momirealms.craftengine.bukkit.item.behavior.WaterBucketItemBehavior;
@@ -69,8 +70,15 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override
public void delayedInit() {
Bukkit.getPluginManager().registerEvents(this.itemEventListener, plugin.bootstrap());
Bukkit.getPluginManager().registerEvents(this.debugStickListener, plugin.bootstrap());
Bukkit.getPluginManager().registerEvents(this.itemEventListener, this.plugin.bootstrap());
Bukkit.getPluginManager().registerEvents(this.debugStickListener, this.plugin.bootstrap());
this.hookExternalPlugins();
}
private void hookExternalPlugins() {
if (this.plugin.isPluginEnabled("NeigeItems")) {
registerExternalItemProvider(new NeigeItemsProvider());
}
}
@Override

View File

@@ -29,7 +29,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;

View File

@@ -299,7 +299,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
}
@Override
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
protected ItemWrapper<ItemStack> mergeCopy(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
Object itemStack1 = item1.getLiteralObject();
Object itemStack2 = item2.getLiteralObject();
try {
@@ -311,4 +311,16 @@ public class ComponentItemFactory extends BukkitItemFactory {
}
return null;
}
@Override
protected void merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
item1.load();
Object itemStack1 = item1.getLiteralObject();
Object itemStack2 = item2.getLiteralObject();
try {
Reflections.method$ItemStack$applyComponents.invoke(itemStack1, Reflections.method$ItemStack$getComponentsPatch.invoke(itemStack2));
} catch (Exception e) {
plugin.logger().warn("Failed to merge item", e);
}
}
}

View File

@@ -234,11 +234,17 @@ public class UniversalItemFactory extends BukkitItemFactory {
}
@Override
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
protected ItemWrapper<ItemStack> mergeCopy(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
Object itemStack = ItemObject.copy(item2.getLiteralObject());
ItemObject.setCustomDataTag(itemStack, TagCompound.clone(ItemObject.getCustomDataTag(item1.getLiteralObject())));
// one more step than vanilla
TagCompound.merge(ItemObject.getCustomDataTag(itemStack), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count());
}
@Override
protected void merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
item1.load();
TagCompound.merge(ItemObject.getCustomDataTag(item1.getLiteralObject()), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
}
}

View File

@@ -10,7 +10,6 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.plugin.command.sender.Sender;
import net.momirealms.craftengine.core.world.BlockPos;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;

View File

@@ -33,7 +33,9 @@ import org.bukkit.util.RayTraceResult;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
public class PacketConsumers {

View File

@@ -280,7 +280,13 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public Item<I> merge(Item<?> another) {
return new AbstractItem<>(this.factory, this.factory.merge(this.item, ((AbstractItem) another).item));
public Item<I> mergeCopy(Item<?> another) {
return new AbstractItem<>(this.factory, this.factory.mergeCopy(this.item, ((AbstractItem) another).item));
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void merge(Item<I> another) {
this.factory.merge(this.item, ((AbstractItem) another).item);
}
}

View File

@@ -23,6 +23,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
protected static final List<Key> VANILLA_ITEMS = new ArrayList<>();
protected static final Map<Key, List<Holder<Key>>> VANILLA_ITEM_TAGS = new HashMap<>();
protected final Map<String, ExternalItemProvider<I>> externalItemProviders = new HashMap<>();
protected final Map<String, Function<Object, ItemModifier<I>>> dataFunctions = new HashMap<>();
protected final Map<Key, CustomItem<I>> customItems = new HashMap<>();
protected final Map<Key, List<Holder<Key>>> customItemTags;
@@ -47,6 +48,18 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
}
}
@Override
public ExternalItemProvider<I> getExternalItemProvider(String name) {
return this.externalItemProviders.get(name);
}
@Override
public boolean registerExternalItemProvider(ExternalItemProvider<I> externalItemProvider) {
if (this.externalItemProviders.containsKey(externalItemProvider.plugin())) return false;
this.externalItemProviders.put(externalItemProvider.plugin(), externalItemProvider);
return true;
}
@Override
public void unload() {
super.clearModelsToGenerate();
@@ -165,6 +178,13 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
}
private void registerFunctions() {
registerDataFunction((obj) -> {
Map<String, Object> data = MiscUtils.castToMap(obj, false);
String plugin = data.get("plugin").toString();
String id = data.get("id").toString();
ExternalItemProvider<I> provider = AbstractItemManager.this.getExternalItemProvider(plugin);
return new ExternalModifier<>(id, Objects.requireNonNull(provider, "Item provider " + plugin + " not found"));
}, "external");
registerDataFunction((obj) -> {
String name = obj.toString();
return new DisplayNameModifier<>(name);

View File

@@ -0,0 +1,11 @@
package net.momirealms.craftengine.core.item;
import org.jetbrains.annotations.Nullable;
public interface ExternalItemProvider<I> {
String plugin();
@Nullable
I build(String id, ItemBuildContext context);
}

View File

@@ -117,5 +117,7 @@ public interface Item<I> {
Object getLiteralObject();
Item<I> merge(Item<?> another);
Item<I> mergeCopy(Item<?> another);
void merge(Item<I> another);
}

View File

@@ -112,5 +112,7 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
protected abstract Optional<Integer> repairCost(ItemWrapper<I> item);
protected abstract ItemWrapper<I> merge(ItemWrapper<I> item1, ItemWrapper<I> item2);
protected abstract ItemWrapper<I> mergeCopy(ItemWrapper<I> item1, ItemWrapper<I> item2);
protected abstract void merge(ItemWrapper<I> item1, ItemWrapper<I> item2);
}

View File

@@ -51,6 +51,10 @@ public interface ItemManager<T> extends Reloadable, ModelGenerator, ConfigSectio
Key customItemId(T itemStack);
ExternalItemProvider<T> getExternalItemProvider(String name);
boolean registerExternalItemProvider(ExternalItemProvider<T> externalItemProvider);
Optional<CustomItem<T>> getCustomItem(Key key);
Optional<List<ItemBehavior>> getItemBehavior(Key key);

View File

@@ -0,0 +1,33 @@
package net.momirealms.craftengine.core.item.modifier;
import net.momirealms.craftengine.core.item.ExternalItemProvider;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.plugin.CraftEngine;
public class ExternalModifier<I> implements ItemModifier<I> {
private final String id;
private final ExternalItemProvider<I> provider;
public ExternalModifier(String id, ExternalItemProvider<I> provider) {
this.id = id;
this.provider = provider;
}
@Override
public String name() {
return "external";
}
@SuppressWarnings("unchecked")
@Override
public void apply(Item<I> item, ItemBuildContext context) {
I another = this.provider.build(id, context);
if (another == null) {
CraftEngine.instance().logger().warn("'" + id + "' could not be found in " + provider.plugin());
return;
}
Item<I> anotherWrapped = (Item<I>) CraftEngine.instance().itemManager().wrap(another);
item.merge(anotherWrapped);
}
}

View File

@@ -96,7 +96,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
Item<T> wrappedResult = (Item<T>) CraftEngine.instance().itemManager().wrap(result);
Item<T> finalResult = wrappedResult;
if (this.mergeComponents) {
finalResult = base.merge(wrappedResult);
finalResult = base.mergeCopy(wrappedResult);
}
for (ItemDataProcessor processor : this.processors) {
processor.accept(base, wrappedResult, finalResult);

View File

@@ -127,11 +127,11 @@ public abstract class CraftEngine implements Plugin {
// delay the reload so other plugins can register some parsers
this.scheduler.sync().runDelayed(() -> {
this.registerParsers();
this.itemManager.delayedInit();
this.reload();
this.guiManager.delayedInit();
this.recipeManager.delayedInit();
this.blockManager.delayedInit();
this.itemManager.delayedInit();
this.worldManager.delayedInit();
this.packManager.delayedInit();
this.furnitureManager.delayedInit();

View File

@@ -3,6 +3,7 @@ include(":shared")
include(":core")
include(":bukkit")
include(":bukkit:legacy")
include(":bukkit:compatibility")
include(":bukkit-loader")
include(":server-mod")
pluginManagement {