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

添加新函数类型

This commit is contained in:
XiaoMoMi
2025-09-12 04:15:45 +08:00
parent 9f7a597d6d
commit e00734d9ab
47 changed files with 590 additions and 107 deletions

View File

@@ -33,7 +33,7 @@ public class MythicItemDrop extends ItemDrop implements IItemDrop {
@Override
public AbstractItemStack getDrop(DropMetadata dropMetadata, double amount) {
ItemBuildContext context = ItemBuildContext.EMPTY;
ItemBuildContext context = ItemBuildContext.empty();
SkillCaster caster = dropMetadata.getCaster();
if (caster != null && caster.getEntity() instanceof AbstractPlayer abstractPlayer) {
Entity bukkitEntity = abstractPlayer.getBukkitEntity();

View File

@@ -33,7 +33,6 @@ public class ExprCustomItem extends SimpleExpression<ItemType> {
private Expression<?> itemIds;
@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
itemIds = exprs[0];
return true;
@@ -49,7 +48,7 @@ public class ExprCustomItem extends SimpleExpression<ItemType> {
if (object instanceof String string) {
CustomItem<ItemStack> customItem = CraftEngineItems.byId(Key.of(string));
if (customItem != null) {
ItemType itemType = new ItemType(customItem.buildItemStack(ItemBuildContext.EMPTY));
ItemType itemType = new ItemType(customItem.buildItemStack(ItemBuildContext.empty()));
items.add(itemType);
}
}

View File

@@ -1,17 +1,25 @@
package net.momirealms.craftengine.bukkit.advancement;
import com.google.gson.JsonElement;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.advancement.AbstractAdvancementManager;
import net.momirealms.craftengine.core.advancement.AdvancementType;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
public class BukkitAdvancementManager extends AbstractAdvancementManager {
private final BukkitCraftEngine plugin;
@@ -33,6 +41,70 @@ public class BukkitAdvancementManager extends AbstractAdvancementManager {
return this.advancementParser;
}
@Override
public void sendToast(Player player, Item<?> icon, Component message, AdvancementType type) {
try {
Object displayInfo = CoreReflections.constructor$DisplayInfo.newInstance(
icon.getLiteralObject(),
ComponentUtils.adventureToMinecraft(message), // title
CoreReflections.instance$Component$empty, // description
VersionHelper.isOrAbove1_20_3() ? Optional.empty() : null, // background
CoreReflections.instance$AdvancementType$values[type.ordinal()],
true, // show toast
false, // announce to chat
true // hidden
);
if (VersionHelper.isOrAbove1_20_2()) {
displayInfo = Optional.of(displayInfo);
}
Object resourceLocation = KeyUtils.toResourceLocation(Key.of("craftengine", "toast"));
Object criterion = VersionHelper.isOrAbove1_20_2() ?
CoreReflections.constructor$Criterion.newInstance(CoreReflections.constructor$ImpossibleTrigger.newInstance(), CoreReflections.constructor$ImpossibleTrigger$TriggerInstance.newInstance()) :
CoreReflections.constructor$Criterion.newInstance(CoreReflections.constructor$ImpossibleTrigger$TriggerInstance.newInstance());
Map<String, Object> criteria = Map.of("impossible", criterion);
Object advancementProgress = CoreReflections.constructor$AdvancementProgress.newInstance();
Object advancement;
if (VersionHelper.isOrAbove1_20_2()) {
Object advancementRequirements = VersionHelper.isOrAbove1_20_3() ?
CoreReflections.constructor$AdvancementRequirements.newInstance(List.of(List.of("impossible"))) :
CoreReflections.constructor$AdvancementRequirements.newInstance((Object) new String[][] {{"impossible"}});
advancement = CoreReflections.constructor$Advancement.newInstance(
Optional.empty(),
displayInfo,
CoreReflections.instance$AdvancementRewards$EMPTY,
criteria,
advancementRequirements,
false
);
CoreReflections.method$AdvancementProgress$update.invoke(advancementProgress, advancementRequirements);
advancement = CoreReflections.constructor$AdvancementHolder.newInstance(resourceLocation, advancement);
} else {
advancement = CoreReflections.constructor$Advancement.newInstance(
resourceLocation,
null, // parent
displayInfo,
CoreReflections.instance$AdvancementRewards$EMPTY,
criteria,
new String[][] {{"impossible"}},
false
);
CoreReflections.method$AdvancementProgress$update.invoke(advancementProgress, criteria, new String[][] {{"impossible"}});
}
CoreReflections.method$AdvancementProgress$grantProgress.invoke(advancementProgress, "impossible");
Map<Object, Object> advancementsToGrant = new HashMap<>();
advancementsToGrant.put(resourceLocation, advancementProgress);
Object grantPacket = VersionHelper.isOrAbove1_21_5() ?
NetworkReflections.constructor$ClientboundUpdateAdvancementsPacket.newInstance(false, Arrays.asList(advancement), new HashSet<>(), advancementsToGrant, true) :
NetworkReflections.constructor$ClientboundUpdateAdvancementsPacket.newInstance(false, Arrays.asList(advancement), new HashSet<>(), advancementsToGrant);
Object removePacket = VersionHelper.isOrAbove1_21_5() ?
NetworkReflections.constructor$ClientboundUpdateAdvancementsPacket.newInstance(false, new ArrayList<>(), new HashSet<>() {{add(resourceLocation);}}, new HashMap<>(), true) :
NetworkReflections.constructor$ClientboundUpdateAdvancementsPacket.newInstance(false, new ArrayList<>(), new HashSet<>() {{add(resourceLocation);}}, new HashMap<>());
player.sendPackets(List.of(grantPacket, removePacket), false);
} catch (ReflectiveOperationException e) {
this.plugin.logger().warn("Failed to send toast for player " + player.name(), e);
}
}
public class AdvancementParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"advancements", "advancement"};

View File

@@ -129,7 +129,7 @@ public class ConcretePowderBlockBehavior extends BukkitBlockBehavior {
Object mutablePos = CoreReflections.method$BlockPos$mutable.invoke(pos);
int j = Direction.values().length;
for (int k = 0; k < j; k++) {
Object direction = CoreReflections.instance$Directions[k];
Object direction = CoreReflections.instance$Direction$values[k];
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, mutablePos);
if (direction != CoreReflections.instance$Direction$DOWN || canSolidify(blockState)) {
CoreReflections.method$MutableBlockPos$setWithOffset.invoke(mutablePos, pos, direction);

View File

@@ -132,7 +132,7 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
Object mutablePos = CoreReflections.constructor$MutableBlockPos.newInstance();
int j = Direction.values().length;
for (int k = 0; k < j; ++k) {
Object direction = CoreReflections.instance$Directions[k];
Object direction = CoreReflections.instance$Direction$values[k];
CoreReflections.method$MutableBlockPos$setWithOffset.invoke(mutablePos, blockPos, direction);
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, mutablePos);
i = Math.min(i, getDistanceAt(blockState) + 1);

View File

@@ -13,22 +13,21 @@ import java.util.List;
import java.util.UUID;
public class ItemDisplayBlockEntityElement implements BlockEntityElement {
private final ItemDisplayBlockEntityElementConfig config;
private final Object cachedSpawnPacket;
private final Object cachedDespawnPacket;
private final int entityId;
public ItemDisplayBlockEntityElement(ItemDisplayBlockEntityElementConfig config, BlockPos pos) {
int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
Vector3f position = config.position();
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of(
FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entityId, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z,
config.xRot(), config.yRot(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
),
FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(
entityId, config.metadataValues().get()
)
));
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entityId, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z,
config.xRot(), config.yRot(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
);
this.config = config;
this.cachedDespawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(IntList.of(entityId));
this.entityId = entityId;
}
@Override
@@ -38,7 +37,7 @@ public class ItemDisplayBlockEntityElement implements BlockEntityElement {
@Override
public void spawn(Player player) {
player.sendPacket(this.cachedSpawnPacket, true);
player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), true);
}
@Override

View File

@@ -7,9 +7,9 @@ import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityEl
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory;
import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.LazyReference;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.world.BlockPos;
import org.joml.Quaternionf;
@@ -19,11 +19,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementConfig<ItemDisplayBlockEntityElement> {
public static final Factory FACTORY = new Factory();
private final LazyReference<List<Object>> lazyMetadataPacket;
private final LazyReference<Item<?>> item;
private final Function<Player, List<Object>> lazyMetadataPacket;
private final Function<Player, Item<?>> item;
private final Vector3f scale;
private final Vector3f position;
private final Vector3f translation;
@@ -33,7 +34,7 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo
private final ItemDisplayContext displayContext;
private final Billboard billboard;
public ItemDisplayBlockEntityElementConfig(LazyReference<Item<?>> item,
public ItemDisplayBlockEntityElementConfig(Function<Player, Item<?>> item,
Vector3f scale,
Vector3f position,
Vector3f translation,
@@ -51,16 +52,16 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo
this.rotation = rotation;
this.displayContext = displayContext;
this.billboard = billboard;
this.lazyMetadataPacket = LazyReference.lazyReference(() -> {
this.lazyMetadataPacket = player -> {
List<Object> dataValues = new ArrayList<>();
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.get().getLiteralObject(), dataValues);
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.apply(player).getLiteralObject(), dataValues);
ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(this.scale, dataValues);
ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(this.rotation, dataValues);
ItemDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(this.billboard.id(), dataValues);
ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(this.translation, dataValues);
ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(this.displayContext.id(), dataValues);
return dataValues;
});
};
}
@Override
@@ -68,8 +69,8 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo
return new ItemDisplayBlockEntityElement(this, pos);
}
public Item<?> item() {
return this.item.get();
public Item<?> item(Player player) {
return this.item.apply(player);
}
public Vector3f scale() {
@@ -104,8 +105,8 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo
return rotation;
}
public LazyReference<List<Object>> metadataValues() {
return this.lazyMetadataPacket;
public List<Object> metadataValues(Player player) {
return this.lazyMetadataPacket.apply(player);
}
public static class Factory implements BlockEntityElementConfigFactory {
@@ -113,10 +114,9 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo
@SuppressWarnings("unchecked")
@Override
public <E extends BlockEntityElement> BlockEntityElementConfig<E> create(Map<String, Object> arguments) {
// todo item should not be null
Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), ""));
Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item_display.missing_item"));
return (BlockEntityElementConfig<E>) new ItemDisplayBlockEntityElementConfig(
LazyReference.lazyReference(() -> BukkitItemManager.instance().createWrappedItem(itemId, null)),
player -> BukkitItemManager.instance().createWrappedItem(itemId, player),
ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"),
ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position"),
ResourceConfigUtils.getAsVector3f(arguments.get("translation"), "translation"),

View File

@@ -21,7 +21,6 @@ import net.momirealms.craftengine.core.item.recipe.DatapackRecipeResult;
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
import net.momirealms.craftengine.core.pack.AbstractPackManager;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.plugin.logger.Debugger;
import net.momirealms.craftengine.core.util.*;
@@ -335,7 +334,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override
public ItemStack buildCustomItemStack(Key id, Player player) {
return Optional.ofNullable(this.customItemsById.get(id)).map(it -> it.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), 1)).orElse(null);
return Optional.ofNullable(this.customItemsById.get(id)).map(it -> it.buildItemStack(ItemBuildContext.of(player), 1)).orElse(null);
}
@Override

View File

@@ -200,7 +200,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
for (UniqueKey holder : holders) {
Optional<? extends BuildableItem<ItemStack>> buildableItem = BukkitItemManager.instance().getBuildableItem(holder.key());
if (buildableItem.isPresent()) {
ItemStack itemStack = buildableItem.get().buildItemStack(ItemBuildContext.EMPTY, 1);
ItemStack itemStack = buildableItem.get().buildItemStack(ItemBuildContext.empty(), 1);
Object nmsStack = FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack);
itemStacks.add(nmsStack);
} else {
@@ -336,7 +336,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
if (recipe instanceof CustomBrewingRecipe<ItemStack> brewingRecipe) {
if (!VersionHelper.isOrAbove1_20_2()) return;
PotionMix potionMix = new PotionMix(new NamespacedKey(id.namespace(), id.value()),
brewingRecipe.result(ItemBuildContext.EMPTY),
brewingRecipe.result(ItemBuildContext.empty()),
PotionMix.createPredicateChoice(container -> {
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(container);
return brewingRecipe.container().test(UniqueIdItem.of(wrapped));

View File

@@ -23,7 +23,6 @@ import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
import net.momirealms.craftengine.core.item.setting.AnvilRepairItem;
import net.momirealms.craftengine.core.item.setting.ItemEquipment;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.util.*;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -614,9 +613,9 @@ public class RecipeEventListener implements Listener {
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
if (craftingTableRecipe.hasVisualResult()) {
inventory.setResult(craftingTableRecipe.assembleVisual(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
inventory.setResult(craftingTableRecipe.assembleVisual(input, ItemBuildContext.of(serverPlayer)));
} else {
inventory.setResult(craftingTableRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
inventory.setResult(craftingTableRecipe.assemble(input, ItemBuildContext.of(serverPlayer)));
}
}
@@ -642,7 +641,7 @@ public class RecipeEventListener implements Listener {
if (input == null) return;
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
inventory.setResult(craftingTableRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
inventory.setResult(craftingTableRecipe.assemble(input, ItemBuildContext.of(serverPlayer)));
}
private CraftingInput<ItemStack> getCraftingInput(CraftingInventory inventory) {
@@ -694,7 +693,7 @@ public class RecipeEventListener implements Listener {
SmithingInput<ItemStack> input = getSmithingInput(inventory);
if (smithingTrimRecipe.matches(input)) {
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
ItemStack result = smithingTrimRecipe.assemble(getSmithingInput(inventory), new ItemBuildContext(BukkitAdaptors.adapt(player), ContextHolder.EMPTY));
ItemStack result = smithingTrimRecipe.assemble(getSmithingInput(inventory), ItemBuildContext.of(BukkitAdaptors.adapt(player)));
event.setResult(result);
} else {
event.setResult(null);
@@ -718,7 +717,7 @@ public class RecipeEventListener implements Listener {
SmithingInput<ItemStack> input = getSmithingInput(inventory);
if (smithingTransformRecipe.matches(input)) {
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
ItemStack processed = smithingTransformRecipe.assemble(input, new ItemBuildContext(BukkitAdaptors.adapt(player), ContextHolder.EMPTY));
ItemStack processed = smithingTransformRecipe.assemble(input, ItemBuildContext.of(BukkitAdaptors.adapt(player)));
event.setResult(processed);
} else {
event.setResult(null);

View File

@@ -90,7 +90,7 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
return;
}
if (!Config.sendPackOnUpload()) return;
CraftEngine.instance().logger().info("Complete uploading resource pack");
CraftEngine.instance().logger().info("Completed uploading resource pack");
for (BukkitServerPlayer player : this.plugin.networkManager().onlineUsers()) {
sendResourcePack(player);
}

View File

@@ -61,7 +61,7 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
handleFeedback(context, MessageConstants.COMMAND_TOTEM_NOT_TOTEM, Component.text(key.toString()));
return;
}
Item<ItemStack> item = customItem.buildItem(ItemBuildContext.EMPTY);
Item<ItemStack> item = customItem.buildItem(ItemBuildContext.empty());
if (VersionHelper.isOrAbove1_21_2()) {
if (context.flags().contains("sound_location")) {
String soundResourceLocation = context.flags().getValue("sound_location").get().toString();

View File

@@ -112,7 +112,7 @@ public class ProjectilePacketHandler implements EntityPacketHandler {
Optional<CustomItem<ItemStack>> customItem = BukkitItemManager.instance().getCustomItem(this.projectile.metadata().item());
if (customItem.isEmpty()) return itemDisplayValues;
ProjectileMeta meta = this.projectile.metadata();
Item<ItemStack> displayedItem = customItem.get().buildItem(ItemBuildContext.EMPTY);
Item<ItemStack> displayedItem = customItem.get().buildItem(ItemBuildContext.empty());
// 我们应当使用新的展示物品的组件覆盖原物品的组件,以完成附魔,附魔光效等组件的继承
displayedItem = this.projectile.item().mergeCopy(displayedItem);
ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(-1, itemDisplayValues);

View File

@@ -469,17 +469,17 @@ public final class CoreReflections {
public static final Object instance$Direction$SOUTH;
public static final Object instance$Direction$WEST;
public static final Object instance$Direction$EAST;
public static final Object[] instance$Directions;
public static final Object[] instance$Direction$values;
static {
try {
instance$Directions = (Object[]) method$Direction$values.invoke(null);
instance$Direction$DOWN = instance$Directions[0];
instance$Direction$UP = instance$Directions[1];
instance$Direction$NORTH = instance$Directions[2];
instance$Direction$SOUTH = instance$Directions[3];
instance$Direction$WEST = instance$Directions[4];
instance$Direction$EAST = instance$Directions[5];
instance$Direction$values = (Object[]) method$Direction$values.invoke(null);
instance$Direction$DOWN = instance$Direction$values[0];
instance$Direction$UP = instance$Direction$values[1];
instance$Direction$NORTH = instance$Direction$values[2];
instance$Direction$SOUTH = instance$Direction$values[3];
instance$Direction$WEST = instance$Direction$values[4];
instance$Direction$EAST = instance$Direction$values[5];
} catch (ReflectiveOperationException e) {
throw new ReflectionInitException("Failed to init Direction", e);
}
@@ -4217,4 +4217,176 @@ public final class CoreReflections {
public static final Method method$Block$updateEntityMovementAfterFallOn = requireNonNull(
ReflectionUtils.getDeclaredMethod(clazz$Block, void.class, clazz$BlockGetter, clazz$Entity)
);
public static final Class<?> clazz$AdvancementRewards = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.AdvancementRewards",
"advancements.AdvancementRewards"
)
);
public static final Field field$AdvancementRewards$EMPTY = requireNonNull(
ReflectionUtils.getStaticDeclaredField(clazz$AdvancementRewards, clazz$AdvancementRewards, 0)
);
public static final Object instance$AdvancementRewards$EMPTY;
static {
try {
instance$AdvancementRewards$EMPTY = field$AdvancementRewards$EMPTY.get(null);
} catch (ReflectiveOperationException e) {
throw new ReflectionInitException("Failed to initialize AdvancementRewards$EMPTY", e);
}
}
public static final Class<?> clazz$AdvancementRequirements = MiscUtils.requireNonNullIf(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.AdvancementRequirements",
"advancements.AdvancementRequirements"
), VersionHelper.isOrAbove1_20_2()
);
public static final Constructor<?> constructor$AdvancementRequirements = Optional.ofNullable(clazz$AdvancementRequirements)
.map(it -> {
if (VersionHelper.isOrAbove1_20_3()) {
return ReflectionUtils.getConstructor(it, List.class);
} else {
return ReflectionUtils.getConstructor(it, String[][].class);
}
}).orElse(null);
public static final Class<?> clazz$AdvancementProgress = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.AdvancementProgress",
"advancements.AdvancementProgress"
)
);
public static final Constructor<?> constructor$AdvancementProgress = requireNonNull(
ReflectionUtils.getConstructor(clazz$AdvancementProgress)
);
public static final Method method$AdvancementProgress$update = requireNonNull(
VersionHelper.isOrAbove1_20_2() ?
ReflectionUtils.getMethod(clazz$AdvancementProgress, void.class, clazz$AdvancementRequirements) :
ReflectionUtils.getMethod(clazz$AdvancementProgress, void.class, Map.class, String[][].class)
);
public static final Class<?> clazz$AdvancementType = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.AdvancementFrameType",
VersionHelper.isOrAbove1_20_3() ? "advancements.AdvancementType" : "advancements.FrameType"
)
);
public static final Method method$AdvancementType$values = requireNonNull(
ReflectionUtils.getStaticMethod(clazz$AdvancementType, clazz$AdvancementType.arrayType())
);
public static final Object[] instance$AdvancementType$values;
static {
try {
instance$AdvancementType$values = (Object[]) method$AdvancementType$values.invoke(null);
} catch (ReflectiveOperationException e) {
throw new ReflectionInitException("Failed to initialize AdvancementTypes", e);
}
}
public static final Class<?> clazz$DisplayInfo = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.AdvancementDisplay",
"advancements.DisplayInfo"
)
);
public static final Constructor<?> constructor$DisplayInfo = requireNonNull(
VersionHelper.isOrAbove1_20_3() ?
ReflectionUtils.getConstructor(clazz$DisplayInfo, clazz$ItemStack, clazz$Component, clazz$Component, Optional.class, clazz$AdvancementType, boolean.class, boolean.class, boolean.class) :
ReflectionUtils.getConstructor(clazz$DisplayInfo, clazz$ItemStack, clazz$Component, clazz$Component, clazz$ResourceLocation, clazz$AdvancementType, boolean.class, boolean.class, boolean.class)
);
public static final Class<?> clazz$Criterion = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.Criterion",
"advancements.Criterion"
)
);
public static final Class<?> clazz$CriterionTrigger = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.CriterionTrigger",
"advancements.CriterionTrigger"
)
);
public static final Class<?> clazz$CriterionTriggerInstance = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.CriterionInstance",
"advancements.CriterionTriggerInstance"
)
);
public static final Class<?> clazz$ImpossibleTrigger = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.critereon.CriterionTriggerImpossible",
"advancements.critereon.ImpossibleTrigger"
)
);
public static final Constructor<?> constructor$ImpossibleTrigger = requireNonNull(
ReflectionUtils.getConstructor(clazz$ImpossibleTrigger)
);
public static final Class<?> clazz$ImpossibleTrigger$TriggerInstance = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.critereon.CriterionTriggerImpossible$a",
"advancements.critereon.ImpossibleTrigger$TriggerInstance"
)
);
public static final Constructor<?> constructor$Criterion = requireNonNull(
VersionHelper.isOrAbove1_20_2() ?
ReflectionUtils.getConstructor(clazz$Criterion, clazz$CriterionTrigger, clazz$CriterionTriggerInstance) :
ReflectionUtils.getConstructor(clazz$Criterion, clazz$CriterionTriggerInstance)
);
public static final Constructor<?> constructor$ImpossibleTrigger$TriggerInstance = requireNonNull(
ReflectionUtils.getConstructor(clazz$ImpossibleTrigger$TriggerInstance)
);
public static final Class<?> clazz$Advancement = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.Advancement",
"advancements.Advancement"
)
);
public static final Constructor<?> constructor$Advancement = requireNonNull(
VersionHelper.isOrAbove1_20_2() ?
ReflectionUtils.getConstructor(clazz$Advancement, Optional.class, Optional.class, clazz$AdvancementRewards, Map.class, clazz$AdvancementRequirements, boolean.class) :
ReflectionUtils.getConstructor(clazz$Advancement, clazz$ResourceLocation, clazz$Advancement, clazz$DisplayInfo, clazz$AdvancementRewards, Map.class, String[][].class, boolean.class)
);
public static final Class<?> clazz$CriterionProgress = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.CriterionProgress",
"advancements.CriterionProgress"
)
);
public static final Method method$AdvancementProgress$grantProgress = requireNonNull(
ReflectionUtils.getMethod(clazz$AdvancementProgress, boolean.class, new String[]{"grantProgress", "a"}, String.class)
);
public static final Class<?> clazz$AdvancementHolder = MiscUtils.requireNonNullIf(
BukkitReflectionUtils.findReobfOrMojmapClass(
"advancements.AdvancementHolder",
"advancements.AdvancementHolder"
), VersionHelper.isOrAbove1_20_2()
);
public static final Constructor<?> constructor$AdvancementHolder = Optional.ofNullable(clazz$AdvancementHolder)
.map(it -> ReflectionUtils.getConstructor(it, clazz$ResourceLocation, clazz$Advancement))
.orElse(null);
}

View File

@@ -1671,4 +1671,10 @@ public final class NetworkReflections {
"network.protocol.game.ClientboundForgetLevelChunkPacket"
)
);
public static final Constructor<?> constructor$ClientboundUpdateAdvancementsPacket = requireNonNull(
VersionHelper.isOrAbove1_21_5() ?
ReflectionUtils.getConstructor(clazz$ClientboundUpdateAdvancementsPacket, boolean.class, Collection.class, Set.class, Map.class, boolean.class) :
ReflectionUtils.getConstructor(clazz$ClientboundUpdateAdvancementsPacket, boolean.class, Collection.class, Set.class, Map.class)
);
}

View File

@@ -20,6 +20,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MMobEffects
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
import net.momirealms.craftengine.bukkit.util.*;
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.advancement.AdvancementType;
import net.momirealms.craftengine.core.block.BlockStateWrapper;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.entity.BlockEntity;
@@ -235,6 +236,11 @@ public class BukkitServerPlayer extends Player {
return AdventureModeUtils.canPlace(platformPlayer().getInventory().getItemInMainHand(), new Location(platformPlayer().getWorld(), pos.x(), pos.y(), pos.z()), state);
}
@Override
public void sendToast(Component text, Item<?> icon, AdvancementType type) {
this.plugin.advancementManager().sendToast(this, icon, text, type);
}
@Override
public void sendActionBar(Component text) {
Object packet = FastNMS.INSTANCE.constructor$ClientboundActionBarPacket(ComponentUtils.adventureToMinecraft(text));

View File

@@ -261,6 +261,8 @@ warning.config.block.state.missing_state: "<yellow>Issue found in file <arg:0> -
warning.config.block.state.missing_properties: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'properties' section for 'states'.</yellow>"
warning.config.block.state.missing_appearances: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'appearances' section for 'states'.</yellow>"
warning.config.block.state.missing_variants: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'variants' section for 'states'.</yellow>"
warning.config.block.state.entity_renderer.invalid_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an invalid entity renderer type '<arg:2>'.</yellow>"
warning.config.block.state.entity_renderer.item_display.missing_item: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'item' argument for 'item_display' entity renderer.</yellow>"
warning.config.block.state.variant.missing_appearance: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'appearance' argument for variant '<arg:2>'.</yellow>"
warning.config.block.state.variant.invalid_appearance: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' has an error that the variant '<arg:2>' is using a non-existing appearance '<arg:3>'.</yellow>"
warning.config.block.state.invalid_vanilla: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an invalid vanilla block state '<arg:2>'.</yellow>"
@@ -392,7 +394,7 @@ warning.config.function.command.missing_command: "<yellow>Issue found in file <a
warning.config.function.actionbar.missing_actionbar: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'actionbar' argument for 'actionbar' function.</yellow>"
warning.config.function.message.missing_message: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'message' argument for 'message' function.</yellow>"
warning.config.function.open_window.missing_gui_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'gui-type' argument for 'open_window' function.</yellow>"
warning.config.function.open_window.invalid_gui_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid gui type <arg:2> for 'open_window' function. Allowed types: [<arg:3>].</yellow>"
warning.config.function.open_window.invalid_gui_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid gui type '<arg:2>' for 'open_window' function. Allowed types: [<arg:3>].</yellow>"
warning.config.function.run.missing_functions: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'functions' argument for 'run' function.</yellow>"
warning.config.function.place_block.missing_block_state: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'block-state' argument for 'place_block' function.</yellow>"
warning.config.function.set_food.missing_food: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'food' argument for 'set_food' function.</yellow>"
@@ -415,6 +417,14 @@ warning.config.function.remove_cooldown.missing_id: "<yellow>Issue found in file
warning.config.function.mythic_mobs_skill.missing_skill: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'skill' argument for 'mythic_mobs_skill' function.</yellow>"
warning.config.function.spawn_furniture.missing_furniture_id: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'furniture-id' argument for 'spawn_furniture' function.</yellow>"
warning.config.function.replace_furniture.missing_furniture_id: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'furniture-id' argument for 'replace_furniture' function.</yellow>"
warning.config.function.teleport.missing_x: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'x' argument for 'teleport' function.</yellow>"
warning.config.function.teleport.missing_y: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'y' argument for 'teleport' function.</yellow>"
warning.config.function.teleport.missing_z: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'z' argument for 'teleport' function.</yellow>"
warning.config.function.set_variable.missing_name: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'name' argument for 'set_variable' function.</yellow>"
warning.config.function.set_variable.missing_value: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'number' or 'text' argument for 'set_variable' function.</yellow>"
warning.config.function.toast.missing_toast: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'toast' argument for 'toast' function.</yellow>"
warning.config.function.toast.missing_icon: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'icon' argument for 'toast' function.</yellow>"
warning.config.function.toast.invalid_advancement_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid advancement type '<arg:2>' for 'toast' function. Allowed types: [<arg:3>].</yellow>"
warning.config.selector.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for selector.</yellow>"
warning.config.selector.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector type '<arg:2>'.</yellow>"
warning.config.selector.invalid_target: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector target '<arg:2>'.</yellow>"

View File

@@ -8,4 +8,6 @@ public abstract class AbstractAdvancementManager implements AdvancementManager {
public AbstractAdvancementManager(CraftEngine plugin) {
this.plugin = plugin;
}
}

View File

@@ -1,9 +1,14 @@
package net.momirealms.craftengine.core.advancement;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
public interface AdvancementManager extends Manageable {
ConfigParser parser();
void sendToast(Player player, Item<?> icon, Component message, AdvancementType type);
}

View File

@@ -23,8 +23,7 @@ public class BlockEntityElementConfigs {
Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(Key::of).orElse(ITEM_DISPLAY);
BlockEntityElementConfigFactory factory = BuiltInRegistries.BLOCK_ENTITY_ELEMENT_TYPE.getValue(type);
if (factory == null) {
// todo 发送消息
throw new LocalizedResourceConfigException("", type.toString());
throw new LocalizedResourceConfigException("warning.config.block.state.entity_renderer.invalid_type", type.toString());
}
return factory.create(arguments);
}

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.core.entity.player;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.core.advancement.AdvancementType;
import net.momirealms.craftengine.core.entity.AbstractEntity;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.context.CooldownData;
@@ -8,7 +9,6 @@ import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.sound.SoundSource;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.Position;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.jetbrains.annotations.NotNull;
@@ -64,6 +64,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract boolean canPlace(BlockPos pos, Object state);
public abstract void sendToast(Component text, Item<?> icon, AdvancementType type);
public abstract void sendActionBar(Component text);
public abstract void sendMessage(Component text, boolean overlay);

View File

@@ -1,7 +1,6 @@
package net.momirealms.craftengine.core.item;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.util.Key;
public interface BuildableItem<I> {
@@ -27,18 +26,18 @@ public interface BuildableItem<I> {
}
default I buildItemStack() {
return buildItemStack(ItemBuildContext.EMPTY, 1);
return buildItemStack(ItemBuildContext.empty(), 1);
}
default I buildItemStack(int count) {
return buildItemStack(ItemBuildContext.EMPTY, count);
return buildItemStack(ItemBuildContext.empty(), count);
}
default I buildItemStack(Player player) {
return this.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), 1);
return this.buildItemStack(ItemBuildContext.of(player), 1);
}
default I buildItemStack(Player player, int count) {
return this.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), count);
return this.buildItemStack(ItemBuildContext.of(player), count);
}
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.item;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
@@ -10,12 +11,23 @@ import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class ItemBuildContext extends PlayerOptionalContext {
public static final ItemBuildContext EMPTY = new ItemBuildContext(null, ContextHolder.EMPTY);
/**
* Use {@link #empty()} instead
*/
@Deprecated(since = "0.0.63", forRemoval = true)
public static final ItemBuildContext EMPTY = new ItemBuildContext(null, ContextHolder.empty());
public static final TagResolver[] EMPTY_RESOLVERS = empty().tagResolvers();
public ItemBuildContext(@Nullable Player player, @NotNull ContextHolder contexts) {
super(player, contexts);
}
@NotNull
public static ItemBuildContext empty() {
return new ItemBuildContext(null, ContextHolder.empty());
}
@NotNull
public static ItemBuildContext of(@Nullable Player player, @NotNull ContextHolder contexts) {
return new ItemBuildContext(player, contexts);
@@ -29,7 +41,7 @@ public class ItemBuildContext extends PlayerOptionalContext {
@NotNull
public static ItemBuildContext of(@Nullable Player player) {
if (player == null) return new ItemBuildContext(null, ContextHolder.EMPTY);
if (player == null) return new ItemBuildContext(null, ContextHolder.empty());
return new ItemBuildContext(player, new ContextHolder(Map.of(DirectContextParameters.PLAYER, () -> player)));
}
}

View File

@@ -8,7 +8,7 @@ import java.util.Optional;
public abstract class AbstractVanillaLootManager implements VanillaLootManager {
protected final Map<Integer, VanillaLoot> blockLoots = new HashMap<>();
// TODO More entity NBT
// TODO 实现一个基于entity data的生物战利品系统
protected final Map<Key, VanillaLoot> entityLoots = new HashMap<>();
public AbstractVanillaLootManager() {

View File

@@ -467,7 +467,7 @@ public abstract class AbstractPackManager implements PackManager {
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/block/custom/pebble_1.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/block/custom/pebble_2.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/block/custom/pebble_3.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/item/custom/sofa_straight.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/item/custom/sleeper_sofa.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/item/custom/sofa_inner.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/item/custom/sofa.json");
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/item/custom/sofa.png");

View File

@@ -18,6 +18,6 @@ public class PathContext extends AbstractCommonContext {
}
public static PathContext of(Path path) {
return new PathContext(ContextHolder.EMPTY, path);
return new PathContext(ContextHolder.empty(), path);
}
}

View File

@@ -35,7 +35,6 @@ import net.momirealms.craftengine.core.plugin.logger.filter.LogFilter;
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerAdapter;
import net.momirealms.craftengine.core.sound.SoundManager;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.core.plugin.context;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
@@ -10,11 +11,32 @@ import java.util.Optional;
import java.util.function.Supplier;
public class ContextHolder {
/**
* Use {@link #empty()} instead
*/
@Deprecated(forRemoval = true, since = "0.0.63")
public static final ContextHolder EMPTY = ContextHolder.builder().immutable(true).build();
protected final Map<ContextKey<?>, Supplier<Object>> params;
private final boolean immutable;
public ContextHolder(Map<ContextKey<?>, Supplier<Object>> params, boolean immutable) {
this.params = immutable ? ImmutableMap.copyOf(params) : new HashMap<>(params);
this.immutable = immutable;
}
public ContextHolder(Map<ContextKey<?>, Supplier<Object>> params) {
this.params = params;
this.params = new HashMap<>(params);
this.immutable = true;
}
@NotNull
public static ContextHolder empty() {
return ContextHolder.builder().build();
}
public boolean immutable() {
return this.immutable;
}
public boolean has(ContextKey<?> key) {
@@ -67,7 +89,7 @@ public class ContextHolder {
}
public static class Builder {
private final Map<ContextKey<?>, Supplier<Object>> params = new HashMap<>();
private final Map<ContextKey<?>, Supplier<Object>> params = new HashMap<>(8);
private boolean immutable = false;
public Builder() {}
@@ -113,7 +135,7 @@ public class ContextHolder {
}
public ContextHolder build() {
return new ContextHolder(this.immutable ? ImmutableMap.copyOf(this.params) : this.params);
return new ContextHolder(this.params, this.immutable);
}
}

View File

@@ -11,7 +11,12 @@ import java.util.List;
import java.util.Map;
public class PlayerOptionalContext extends AbstractChainParameterContext implements PlayerContext {
public static final PlayerOptionalContext EMPTY = new PlayerOptionalContext(null, ContextHolder.EMPTY);
/**
* Use {@link #empty()} instead
*/
@Deprecated(forRemoval = true)
public static final PlayerOptionalContext EMPTY = new PlayerOptionalContext(null, ContextHolder.empty());
protected final Player player;
public PlayerOptionalContext(@Nullable Player player,
@@ -40,10 +45,15 @@ public class PlayerOptionalContext extends AbstractChainParameterContext impleme
@NotNull
public static PlayerOptionalContext of(@Nullable Player player) {
if (player == null) return EMPTY;
if (player == null) return empty();
return new PlayerOptionalContext(player, new ContextHolder(Map.of(DirectContextParameters.PLAYER, () -> player)));
}
@NotNull
public static PlayerOptionalContext empty() {
return new PlayerOptionalContext(null, ContextHolder.empty());
}
@Override
@Nullable
public Player player() {

View File

@@ -43,6 +43,8 @@ public class EventFunctions {
register(CommonFunctions.REPLACE_FURNITURE, new ReplaceFurnitureFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.MYTHIC_MOBS_SKILL, new MythicMobsSkillFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.TELEPORT, new TeleportFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.SET_VARIABLE, new SetVariableFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.TOAST, new ToastFunction.FactoryImpl<>(EventConditions::fromMap));
}
public static void register(Key key, FunctionFactory<PlayerOptionalContext> factory) {

View File

@@ -33,7 +33,7 @@ public class ActionBarFunction<CTX extends Context> extends AbstractConditionalF
});
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
viewer.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(relationalContext), relationalContext.tagResolvers()));
}
}

View File

@@ -45,7 +45,7 @@ public class CommandFunction<CTX extends Context> extends AbstractConditionalFun
));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
executeCommands(relationalContext, this.asEvent ? viewer::performCommandAsEvent : command1 -> viewer.performCommand(command1, this.asOp));
}
}

View File

@@ -33,4 +33,5 @@ public final class CommonFunctions {
public static final Key MYTHIC_MOBS_SKILL = Key.of("craftengine:mythic_mobs_skill");
public static final Key TELEPORT = Key.of("craftengine:teleport");
public static final Key TOAST = Key.of("craftengine:toast");
public static final Key SET_VARIABLE = Key.of("craftengine:set_variable");
}

View File

@@ -36,7 +36,7 @@ public class LevelerExpFunction<CTX extends Context> extends AbstractConditional
});
} else {
for (Player target : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target));
CraftEngine.instance().compatibilityManager().addLevelerExp(target, this.plugin, this.leveler, this.count.getDouble(relationalContext));
}
}

View File

@@ -38,7 +38,7 @@ public class MessageFunction<CTX extends Context> extends AbstractConditionalFun
});
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
for (TextProvider c : this.messages) {
viewer.sendMessage(AdventureHelper.miniMessage().deserialize(c.get(relationalContext), relationalContext.tagResolvers()), this.overlay);
}

View File

@@ -46,7 +46,7 @@ public class OpenWindowFunction<CTX extends Context> extends AbstractConditional
for (Player viewer : this.selector.get(ctx)) {
CraftEngine.instance().guiManager().openInventory(viewer, this.guiType);
if (this.optionalTitle != null) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
CraftEngine.instance().guiManager().updateInventoryTitle(viewer, AdventureHelper.miniMessage().deserialize(this.optionalTitle.get(relationalContext), relationalContext.tagResolvers()));
}
}

View File

@@ -39,7 +39,7 @@ public class PotionEffectFunction<CTX extends Context> extends AbstractCondition
});
} else {
for (Player target : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target));
target.addPotionEffect(this.potionEffectType, this.duration.getInt(relationalContext), this.amplifier.getInt(relationalContext), this.ambient, this.particles);
}
}

View File

@@ -41,7 +41,7 @@ public class SetCooldownFunction<CTX extends Context> extends AbstractConditiona
});
} else {
for (Player target : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target));
long millis = TimeUtils.parseToMillis(this.time.get(relationalContext));
CooldownData data = target.cooldown();
if (this.add) data.addCooldown(this.id, millis);

View File

@@ -33,7 +33,7 @@ public class SetFoodFunction<CTX extends Context> extends AbstractConditionalFun
optionalPlayer.ifPresent(player -> player.setFoodLevel(this.add ? player.foodLevel() + this.count.getInt(ctx) : this.count.getInt(ctx)));
} else {
for (Player target : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target));
target.setFoodLevel(this.add ? target.foodLevel() + this.count.getInt(relationalContext) : this.count.getInt(relationalContext));
}
}

View File

@@ -33,7 +33,7 @@ public class SetSaturationFunction<CTX extends Context> extends AbstractConditio
optionalPlayer.ifPresent(player -> player.setSaturation(this.add ? player.saturation() + this.count.getFloat(ctx) : this.count.getFloat(ctx)));
} else {
for (Player target : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(target));
target.setSaturation(this.add ? target.saturation() + this.count.getFloat(relationalContext) : this.count.getFloat(relationalContext));
}
}

View File

@@ -0,0 +1,72 @@
package net.momirealms.craftengine.core.plugin.context.function;
import com.mojang.datafixers.util.Either;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.ContextKey;
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.List;
import java.util.Map;
public class SetVariableFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final Either<TextProvider, NumberProvider> either;
private final String variableName;
private final boolean asInt;
public SetVariableFunction(List<Condition<CTX>> predicates, String variableName, Either<TextProvider, NumberProvider> either, boolean asInt) {
super(predicates);
this.either = either;
this.variableName = variableName;
this.asInt = asInt;
}
@Override
public void runInternal(CTX ctx) {
ContextHolder contexts = ctx.contexts();
if (contexts.immutable()) return;
this.either.ifLeft(text -> contexts.withParameter(ContextKey.direct("var_" + this.variableName), text.get(ctx)))
.ifRight(number -> contexts.withParameter(ContextKey.direct("var_" + this.variableName), asInt ? number.getInt(ctx) : number.getDouble(ctx)));
}
@Override
public Key type() {
return CommonFunctions.SET_VARIABLE;
}
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
super(factory);
}
@Override
public Function<CTX> create(Map<String, Object> arguments) {
String variableName = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("name"), "warning.config.function.set_variable.missing_name");
if (arguments.containsKey("number")) {
return new SetVariableFunction<>(
getPredicates(arguments),
variableName,
Either.right(NumberProviders.fromObject(arguments.get("number"))),
ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("as-int", false), "as-int")
);
} else if (arguments.containsKey("text")) {
return new SetVariableFunction<>(
getPredicates(arguments),
variableName,
Either.left(TextProviders.fromString(arguments.get("text").toString())),
false
);
} else {
throw new LocalizedResourceConfigException("warning.config.function.set_variable.missing_value");
}
}
}
}

View File

@@ -2,7 +2,6 @@ package net.momirealms.craftengine.core.plugin.context.function;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.Platform;
import net.momirealms.craftengine.core.plugin.context.*;
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
@@ -11,19 +10,14 @@ import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Text;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
public class TeleportFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final PlayerSelector<CTX> selector;
@@ -47,22 +41,21 @@ public class TeleportFunction<CTX extends Context> extends AbstractConditionalFu
this.yaw = yaw;
}
@SuppressWarnings("DuplicatedCode")
@Override
public void runInternal(CTX ctx) {
if (this.selector == null) {
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
it.teleport(new WorldPosition(
Optional.ofNullable(this.world).map(w -> w.get(ctx)).map(w -> CraftEngine.instance().platform().getWorld(w)).orElse(it.world()),
this.x.getDouble(ctx),
this.y.getDouble(ctx),
this.z.getDouble(ctx),
this.pitch.getFloat(ctx),
this.yaw.getFloat(ctx))
);
});
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> it.teleport(new WorldPosition(
Optional.ofNullable(this.world).map(w -> w.get(ctx)).map(w -> CraftEngine.instance().platform().getWorld(w)).orElse(it.world()),
this.x.getDouble(ctx),
this.y.getDouble(ctx),
this.z.getDouble(ctx),
this.pitch.getFloat(ctx),
this.yaw.getFloat(ctx))
));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
viewer.teleport(new WorldPosition(
Optional.ofNullable(this.world).map(w -> w.get(relationalContext)).map(w -> CraftEngine.instance().platform().getWorld(w)).orElse(viewer.world()),
this.x.getDouble(relationalContext),

View File

@@ -45,7 +45,7 @@ public class TitleFunction<CTX extends Context> extends AbstractConditionalFunct
));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
viewer.sendTitle(
AdventureHelper.miniMessage().deserialize(this.main.get(relationalContext), relationalContext.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub.get(relationalContext), relationalContext.tagResolvers()),

View File

@@ -0,0 +1,87 @@
package net.momirealms.craftengine.core.plugin.context.function;
import net.momirealms.craftengine.core.advancement.AdvancementType;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemKeys;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.context.*;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.EnumUtils;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
public class ToastFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final PlayerSelector<CTX> selector;
private final TextProvider toast;
private final java.util.function.Function<Player, Item<?>> icon;
private final AdvancementType advancementType;
public ToastFunction(List<Condition<CTX>> predicates,
@Nullable PlayerSelector<CTX> selector,
TextProvider toast,
java.util.function.Function<Player, Item<?>> icon,
AdvancementType advancementType) {
super(predicates);
this.selector = selector;
this.toast = toast;
this.icon = icon;
this.advancementType = advancementType;
}
@Override
public void runInternal(CTX ctx) {
if (this.selector == null) {
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> it.sendToast(AdventureHelper.miniMessage().deserialize(this.toast.get(ctx), ctx.tagResolvers()), this.icon.apply(it), this.advancementType));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
viewer.sendToast(AdventureHelper.miniMessage().deserialize(this.toast.get(relationalContext), relationalContext.tagResolvers()), this.icon.apply(viewer), this.advancementType);
}
}
}
@Override
public Key type() {
return CommonFunctions.TOAST;
}
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
super(factory);
}
@Override
public Function<CTX> create(Map<String, Object> arguments) {
AdvancementType advancementType;
String advancementName = arguments.getOrDefault("advancement-type", "goal").toString();
try {
advancementType = AdvancementType.valueOf(advancementName.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
throw new LocalizedResourceConfigException("warning.config.function.toast.invalid_advancement_type", advancementName, EnumUtils.toString(AdvancementType.values()));
}
String toast = ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "toast", "message"), "warning.config.function.toast.missing_toast");
Key item = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "item", "icon"), "warning.config.function.toast.missing_icon"));
return new ToastFunction<>(
getPredicates(arguments),
PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()),
TextProviders.fromString(toast),
player -> CraftEngine.instance().itemManager().createWrappedItem(item, player),
advancementType
);
}
}
}

View File

@@ -161,8 +161,8 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
this.plugin.logger().warn("Can't not find item " + it.icon() + " for category icon");
return null;
}
item.customNameJson(AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(it.displayName(), ItemBuildContext.EMPTY.tagResolvers())));
item.loreJson(it.displayLore().stream().map(lore -> AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(lore, ItemBuildContext.EMPTY.tagResolvers()))).toList());
item.customNameJson(AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(it.displayName(), ItemBuildContext.EMPTY_RESOLVERS)));
item.loreJson(it.displayLore().stream().map(lore -> AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(lore, ItemBuildContext.EMPTY_RESOLVERS))).toList());
return new ItemWithAction(item, (element, click) -> {
click.cancel();
player.playSound(Constants.SOUND_CLICK_BUTTON);
@@ -245,12 +245,12 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
if (ItemUtils.isEmpty(item)) {
if (!subCategory.icon().equals(ItemKeys.AIR)) {
item = this.plugin.itemManager().createWrappedItem(ItemKeys.BARRIER, player);
item.customNameJson(AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(subCategory.displayName(), ItemBuildContext.EMPTY.tagResolvers())));
item.loreJson(subCategory.displayLore().stream().map(lore -> AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(lore, ItemBuildContext.EMPTY.tagResolvers()))).toList());
item.customNameJson(AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(subCategory.displayName(), ItemBuildContext.EMPTY_RESOLVERS)));
item.loreJson(subCategory.displayLore().stream().map(lore -> AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(lore, ItemBuildContext.EMPTY_RESOLVERS))).toList());
}
} else {
item.customNameJson(AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(subCategory.displayName(), ItemBuildContext.EMPTY.tagResolvers())));
item.loreJson(subCategory.displayLore().stream().map(lore -> AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(lore, ItemBuildContext.EMPTY.tagResolvers()))).toList());
item.customNameJson(AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(subCategory.displayName(), ItemBuildContext.EMPTY_RESOLVERS)));
item.loreJson(subCategory.displayLore().stream().map(lore -> AdventureHelper.componentToJson(AdventureHelper.miniMessage().deserialize(lore, ItemBuildContext.EMPTY_RESOLVERS))).toList());
}
return new ItemWithAction(item, (element, click) -> {
click.cancel();

View File

@@ -111,6 +111,22 @@ public class ReflectionUtils {
return null;
}
@Nullable
public static Field getStaticDeclaredField(final Class<?> clazz, final Class<?> type, final int index) {
int i = 0;
for (final Field field : clazz.getDeclaredFields()) {
if (field.getType() == type) {
if (Modifier.isStatic(field.getModifiers())) {
if (index == i) {
return setAccessible(field);
}
i++;
}
}
}
return null;
}
@Nullable
public static Field getDeclaredField(final Class<?> clazz, final Class<?> type, int index) {
int i = 0;

View File

@@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx1G
# Project settings
# Rule: [major update].[feature update].[bug fix]
project_version=0.0.62.17
project_version=0.0.62.18
config_version=45
lang_version=26
lang_version=27
project_group=net.momirealms
latest_supported_version=1.21.8