mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +00:00
Merge branch 'Xiao-MoMi:dev' into dev
This commit is contained in:
@@ -46,14 +46,12 @@ import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
private static int[] ordinalToIbdID;
|
||||
private final Extent extent;
|
||||
private final Set<CEChunk> chunksToSave;
|
||||
private final CEWorld ceWorld;
|
||||
private final Set<ChunkPos> brokenChunks = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
protected FastAsyncWorldEditDelegate(EditSessionEvent event, Extent extent) {
|
||||
super(extent);
|
||||
this.extent = extent;
|
||||
this.chunksToSave = new HashSet<>();
|
||||
World weWorld = event.getWorld();
|
||||
org.bukkit.World world = Bukkit.getWorld(requireNonNull(weWorld).getName());
|
||||
@@ -77,8 +75,9 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
public void onEditSessionEvent(EditSessionEvent event) {
|
||||
World weWorld = event.getWorld();
|
||||
if (weWorld == null) return;
|
||||
Extent currentExtent = event.getExtent();
|
||||
if (event.getStage() == EditSession.Stage.BEFORE_CHANGE) {
|
||||
event.setExtent(new FastAsyncWorldEditDelegate(event, event.getExtent()));
|
||||
event.setExtent(new FastAsyncWorldEditDelegate(event, currentExtent));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -138,7 +137,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) {
|
||||
boolean result = extent.setBlock(x, y, z, block);
|
||||
boolean result = super.setBlock(x, y, z, block);
|
||||
if (result) {
|
||||
Mask mask = getMask();
|
||||
if (mask != null && !mask.test(BlockVector3.at(x, y, z))) return true;
|
||||
|
||||
@@ -42,13 +42,13 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> buildItem(ItemBuildContext context) {
|
||||
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(this.item, 1));
|
||||
public Item<ItemStack> buildItem(ItemBuildContext context, int count) {
|
||||
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(this.item, count));
|
||||
Item<ItemStack> wrapped = BukkitCraftEngine.instance().itemManager().wrap(item);
|
||||
for (ItemDataModifier<ItemStack> modifier : dataModifiers()) {
|
||||
modifier.apply(wrapped, context);
|
||||
}
|
||||
return BukkitCraftEngine.instance().itemManager().wrap(wrapped.getItem());
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
public Object clientItem() {
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
@@ -28,8 +29,6 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -39,6 +38,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
static {
|
||||
@@ -56,8 +56,10 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
private final Object bedrockItemHolder;
|
||||
private final Item<ItemStack> emptyItem;
|
||||
private final UniqueIdItem<ItemStack> emptyUniqueItem;
|
||||
private final Function<Object, Integer> decoratedHashOpsGenerator;
|
||||
private Set<Key> lastRegisteredPatterns = Set.of();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BukkitItemManager(BukkitCraftEngine plugin) {
|
||||
super(plugin);
|
||||
instance = this;
|
||||
@@ -68,13 +70,14 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
this.armorEventListener = new ArmorEventListener();
|
||||
this.networkItemHandler = VersionHelper.isOrAbove1_20_5() ? new ModernNetworkItemHandler() : new LegacyNetworkItemHandler();
|
||||
this.registerAllVanillaItems();
|
||||
this.bedrockItemHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(Key.of("minecraft:bedrock")))).get();;
|
||||
this.bedrockItemHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(Key.of("minecraft:bedrock")))).get();
|
||||
this.registerCustomTrimMaterial();
|
||||
this.loadLastRegisteredPatterns();
|
||||
|
||||
ItemStack emptyStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.instance$ItemStack$EMPTY);
|
||||
this.emptyItem = this.wrap(emptyStack);
|
||||
this.emptyUniqueItem = new UniqueIdItem<>(UniqueKey.AIR, this.emptyItem);
|
||||
this.decoratedHashOpsGenerator = VersionHelper.isOrAbove1_21_5() ? (Function<Object, Integer>) FastNMS.INSTANCE.createDecoratedHashOpsGenerator(MRegistryOps.HASHCODE) : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -160,11 +163,11 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
|
||||
@Override
|
||||
public Optional<BuildableItem<ItemStack>> getVanillaItem(Key key) {
|
||||
Material material = Registry.MATERIAL.get(KeyUtils.toNamespacedKey(key));
|
||||
if (material == null) {
|
||||
ItemStack vanilla = createVanillaItemStack(key);
|
||||
if (vanilla == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new CloneableConstantItem(key, new ItemStack(material)));
|
||||
return Optional.of(new CloneableConstantItem(key, this.wrap(vanilla)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -452,4 +455,9 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
}
|
||||
return this.emptyItem;
|
||||
}
|
||||
|
||||
@Nullable // 1.21.5+
|
||||
public Function<Object, Integer> decoratedHashOpsGenerator() {
|
||||
return decoratedHashOpsGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.momirealms.craftengine.core.item.BuildableItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class CloneableConstantItem implements BuildableItem<ItemStack> {
|
||||
private final ItemStack item;
|
||||
private final Item<ItemStack> item;
|
||||
private final Key id;
|
||||
|
||||
public CloneableConstantItem(Key id, ItemStack item) {
|
||||
public CloneableConstantItem(Key id, Item<ItemStack> item) {
|
||||
this.item = item;
|
||||
this.id = id;
|
||||
}
|
||||
@@ -19,10 +20,13 @@ public class CloneableConstantItem implements BuildableItem<ItemStack> {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> buildItem(ItemBuildContext context, int count) {
|
||||
return this.item.copyWithCount(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack buildItemStack(ItemBuildContext context, int count) {
|
||||
ItemStack itemStack = this.item.clone();
|
||||
itemStack.setAmount(count);
|
||||
return itemStack;
|
||||
return this.item.copyWithCount(count).getItem();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
case "1.21.4" -> {
|
||||
return new ComponentItemFactory1_21_4(plugin);
|
||||
}
|
||||
case "1.21.5", "1.21.6", "1.21.7", "1.22", "1.22.1" -> {
|
||||
case "1.21.5", "1.21.6", "1.21.7", "1.21.8" -> {
|
||||
return new ComponentItemFactory1_21_5(plugin);
|
||||
}
|
||||
default -> throw new IllegalStateException("Unsupported server version: " + plugin.serverVersion());
|
||||
|
||||
@@ -561,7 +561,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
CustomStoneCuttingRecipe<ItemStack> ceRecipe = new CustomStoneCuttingRecipe<>(
|
||||
id, recipe.group(), Ingredient.of(holders),
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
|
||||
);
|
||||
this.registerInternalRecipe(id, ceRecipe);
|
||||
}
|
||||
@@ -590,7 +590,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
CustomShapelessRecipe<ItemStack> ceRecipe = new CustomShapelessRecipe<>(
|
||||
id, recipe.category(), recipe.group(), ingredientList,
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
|
||||
);
|
||||
if (hasCustomItemInTag) {
|
||||
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
|
||||
@@ -627,7 +627,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
CustomShapedRecipe<ItemStack> ceRecipe = new CustomShapedRecipe<>(
|
||||
id, recipe.category(), recipe.group(),
|
||||
new CustomShapedRecipe.Pattern<>(recipe.pattern(), ingredients),
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
|
||||
);
|
||||
if (hasCustomItemInTag) {
|
||||
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
|
||||
@@ -651,7 +651,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
id, recipe.category(), recipe.group(),
|
||||
Ingredient.of(holders),
|
||||
recipe.cookingTime(), recipe.experience(),
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
|
||||
);
|
||||
if (hasCustomItemInTag) {
|
||||
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
|
||||
@@ -680,7 +680,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
baseHolders.isEmpty() ? null : Ingredient.of(baseHolders),
|
||||
templateHolders.isEmpty() ? null : Ingredient.of(templateHolders),
|
||||
additionHolders.isEmpty() ? null : Ingredient.of(additionHolders),
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()),
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null),
|
||||
true,
|
||||
List.of()
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.plugin.command.FlagKeys;
|
||||
import net.momirealms.craftengine.core.plugin.locale.MessageConstants;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -74,9 +75,17 @@ public class GiveItemCommand extends BukkitCommandFeature<CommandSender> {
|
||||
ItemStack more = builtItem.clone();
|
||||
more.setAmount(perStackSize);
|
||||
if (toInv) {
|
||||
PlayerUtils.putItemsToInventory(player.getInventory(), more, more.getAmount());
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.getScheduler().run(plugin().javaPlugin(), (t) -> PlayerUtils.putItemsToInventory(player.getInventory(), more, more.getAmount()), () -> {});
|
||||
} else {
|
||||
PlayerUtils.putItemsToInventory(player.getInventory(), more, more.getAmount());
|
||||
}
|
||||
} else {
|
||||
PlayerUtils.dropItem(player, more, false, true, false);
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.getScheduler().run(plugin().javaPlugin(), (t) -> PlayerUtils.dropItem(player, more, false, true, false), () -> {});
|
||||
} else {
|
||||
PlayerUtils.dropItem(player, more, false, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.SET_EQUIPMENT, this.packetIds.clientboundSetEquipmentPacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.SET_PLAYER_INVENTORY_1_21_2, this.packetIds.clientboundSetPlayerInventoryPacket());
|
||||
registerC2SByteBufPacketConsumer(PacketConsumers.SET_CREATIVE_MODE_SLOT, this.packetIds.serverboundSetCreativeModeSlotPacket());
|
||||
registerC2SByteBufPacketConsumer(PacketConsumers.CONTAINER_CLICK_1_20, this.packetIds.serverboundContainerClickPacket());
|
||||
registerC2SByteBufPacketConsumer(VersionHelper.isOrAbove1_21_5() ? PacketConsumers.CONTAINER_CLICK_1_21_5 : PacketConsumers.CONTAINER_CLICK_1_20, this.packetIds.serverboundContainerClickPacket());
|
||||
registerC2SByteBufPacketConsumer(PacketConsumers.INTERACT_ENTITY, this.packetIds.serverboundInteractPacket());
|
||||
}
|
||||
|
||||
|
||||
@@ -2124,23 +2124,6 @@ public class PacketConsumers {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemStack);
|
||||
if (!wrapped.isEmpty() && wrapped.isCustomItem()) {
|
||||
Object containerMenu = FastNMS.INSTANCE.field$Player$containerMenu(serverPlayer.serverPlayer());
|
||||
if (containerMenu != null) {
|
||||
ItemStack carried = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.method$AbstractContainerMenu$getCarried(containerMenu));
|
||||
if (ItemStackUtils.isEmpty(carried)) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
|
||||
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, carried);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BukkitItemManager.instance().s2c(itemStack, serverPlayer).ifPresent((newItemStack) -> {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
@@ -2245,9 +2228,70 @@ public class PacketConsumers {
|
||||
}
|
||||
};
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> CONTAINER_CLICK_1_21_5 = (user, event) -> {
|
||||
try {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
boolean changed = false;
|
||||
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
|
||||
Object inventory = FastNMS.INSTANCE.method$Player$getInventory(user.serverPlayer());
|
||||
int containerId = buf.readContainerId();
|
||||
int stateId = buf.readVarInt();
|
||||
short slotNum = buf.readShort();
|
||||
byte buttonNum = buf.readByte();
|
||||
int clickType = buf.readVarInt();
|
||||
int i = buf.readVarInt();
|
||||
Int2ObjectMap<Object> changedSlots = new Int2ObjectOpenHashMap<>(i);
|
||||
for (int j = 0; j < i; ++j) {
|
||||
int k = buf.readShort();
|
||||
Object hashedStack = FastNMS.INSTANCE.method$StreamDecoder$decode(NetworkReflections.instance$HashedStack$STREAM_CODEC, friendlyBuf);
|
||||
Object serverSideItemStack = FastNMS.INSTANCE.method$Container$getItem(inventory, k);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(serverSideItemStack).clone(), ((net.momirealms.craftengine.core.entity.player.Player) user));
|
||||
if (optional.isPresent()) {
|
||||
Object clientSideItemStack = FastNMS.INSTANCE.field$CraftItemStack$handle(optional.get());
|
||||
boolean isSync = FastNMS.INSTANCE.method$HashedStack$matches(hashedStack, clientSideItemStack, BukkitItemManager.instance().decoratedHashOpsGenerator());
|
||||
if (isSync) {
|
||||
changed = true;
|
||||
hashedStack = FastNMS.INSTANCE.method$HashedStack$create(serverSideItemStack, BukkitItemManager.instance().decoratedHashOpsGenerator());
|
||||
}
|
||||
}
|
||||
changedSlots.put(k, hashedStack);
|
||||
}
|
||||
Object carriedHashedStack = FastNMS.INSTANCE.method$StreamDecoder$decode(NetworkReflections.instance$HashedStack$STREAM_CODEC, friendlyBuf);
|
||||
Object containerMenu = FastNMS.INSTANCE.field$Player$containerMenu(user.serverPlayer());
|
||||
Object serverSideCarriedItemStack = FastNMS.INSTANCE.method$AbstractContainerMenu$getCarried(containerMenu);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(serverSideCarriedItemStack).clone(), ((net.momirealms.craftengine.core.entity.player.Player) user));
|
||||
if (optional.isPresent()) {
|
||||
Object clientSideCarriedItemStack = FastNMS.INSTANCE.field$CraftItemStack$handle(optional.get());
|
||||
boolean isSync = FastNMS.INSTANCE.method$HashedStack$matches(carriedHashedStack, clientSideCarriedItemStack, BukkitItemManager.instance().decoratedHashOpsGenerator());
|
||||
if (isSync) {
|
||||
changed = true;
|
||||
carriedHashedStack = FastNMS.INSTANCE.method$HashedStack$create(serverSideCarriedItemStack, BukkitItemManager.instance().decoratedHashOpsGenerator());
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeContainerId(containerId);
|
||||
buf.writeVarInt(stateId);
|
||||
buf.writeShort(slotNum);
|
||||
buf.writeByte(buttonNum);
|
||||
buf.writeVarInt(clickType);
|
||||
buf.writeVarInt(changedSlots.size());
|
||||
Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
|
||||
changedSlots.forEach((k, v) -> {
|
||||
buf.writeShort(k);
|
||||
FastNMS.INSTANCE.method$StreamEncoder$encode(NetworkReflections.instance$HashedStack$STREAM_CODEC, newFriendlyBuf, v);
|
||||
});
|
||||
FastNMS.INSTANCE.method$StreamEncoder$encode(NetworkReflections.instance$HashedStack$STREAM_CODEC, newFriendlyBuf, carriedHashedStack);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundContainerClickPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> CONTAINER_CLICK_1_20 = (user, event) -> {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_21_5()) return; // 1.21.5+需要其他办法解决同步问题
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
boolean changed = false;
|
||||
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
|
||||
|
||||
@@ -3850,4 +3850,27 @@ public final class CoreReflections {
|
||||
CoreReflections.clazz$BlockHitResult, CoreReflections.clazz$Vec3, CoreReflections.clazz$Direction, CoreReflections.clazz$BlockPos, boolean.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$HashOps = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("util.HashOps")),
|
||||
VersionHelper.isOrAbove1_21_5()
|
||||
);
|
||||
|
||||
public static final Field field$HashOps$CRC32C_INSTANCE = Optional.ofNullable(clazz$HashOps)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, it, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Object instance$HashOps$CRC32C_INSTANCE;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
instance$HashOps$CRC32C_INSTANCE = field$HashOps$CRC32C_INSTANCE.get(null);
|
||||
} else {
|
||||
instance$HashOps$CRC32C_INSTANCE = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize HashOps", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import com.google.common.hash.HashCode;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
@@ -12,6 +13,7 @@ import net.momirealms.sparrow.nbt.Tag;
|
||||
import net.momirealms.sparrow.nbt.codec.LegacyJavaOps;
|
||||
import net.momirealms.sparrow.nbt.codec.LegacyNBTOps;
|
||||
import net.momirealms.sparrow.nbt.codec.NBTOps;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -21,6 +23,7 @@ public final class MRegistryOps {
|
||||
public static final DynamicOps<Tag> SPARROW_NBT;
|
||||
public static final DynamicOps<Object> JAVA;
|
||||
public static final DynamicOps<JsonElement> JSON;
|
||||
public static final @Nullable DynamicOps<HashCode> HASHCODE; // 1.21.5+
|
||||
|
||||
// 1.20.5+
|
||||
public static final Class<?> clazz$JavaOps = ReflectionUtils.getClazz("com.mojang.serialization.JavaOps");
|
||||
@@ -47,6 +50,7 @@ public final class MRegistryOps {
|
||||
NBT = (DynamicOps<Object>) CoreReflections.method$RegistryOps$create.invoke(null, ReflectionUtils.getDeclaredField(clazz$NbtOps, clazz$NbtOps, 0).get(null), FastNMS.INSTANCE.registryAccess());
|
||||
JSON = (DynamicOps<JsonElement>) CoreReflections.method$RegistryOps$create.invoke(null, JsonOps.INSTANCE, FastNMS.INSTANCE.registryAccess());
|
||||
SPARROW_NBT = (DynamicOps<Tag>) CoreReflections.method$RegistryOps$create.invoke(null, VersionHelper.isOrAbove1_20_5() ? NBTOps.INSTANCE : LegacyNBTOps.INSTANCE, FastNMS.INSTANCE.registryAccess());
|
||||
HASHCODE = VersionHelper.isOrAbove1_21_5() ? (DynamicOps<HashCode>) CoreReflections.method$RegistryOps$create.invoke(null, CoreReflections.instance$HashOps$CRC32C_INSTANCE, FastNMS.INSTANCE.registryAccess()) : null;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init DynamicOps", e);
|
||||
}
|
||||
|
||||
@@ -1594,4 +1594,31 @@ public final class NetworkReflections {
|
||||
List.of("network.protocol.common.ClientboundUpdateTagsPacket", "network.protocol.game.ClientboundUpdateTagsPacket")
|
||||
)
|
||||
);
|
||||
|
||||
// 1.21.5+
|
||||
public static final Class<?> clazz$HashedStack = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.HashedStack")
|
||||
),
|
||||
VersionHelper.isOrAbove1_21_5()
|
||||
);
|
||||
|
||||
// 1.21.5+
|
||||
public static final Field field$HashedStack$STREAM_CODEC = Optional.ofNullable(clazz$HashedStack)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, clazz$StreamCodec, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Object instance$HashedStack$STREAM_CODEC;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
instance$HashedStack$STREAM_CODEC = field$HashedStack$STREAM_CODEC.get(null);
|
||||
} else {
|
||||
instance$HashedStack$STREAM_CODEC = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize HashedStack$STREAM_CODEC", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.util.MathUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@@ -93,6 +93,11 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Object, ItemDataModifier<I>> getDataType(String key) {
|
||||
return this.dataFunctions.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigParser[] parsers() {
|
||||
return new ConfigParser[]{this.itemParser, this.equipmentParser};
|
||||
|
||||
@@ -8,6 +8,16 @@ public interface BuildableItem<I> {
|
||||
|
||||
Key id();
|
||||
|
||||
Item<I> buildItem(ItemBuildContext context, int count);
|
||||
|
||||
default Item<I> buildItem(Player player) {
|
||||
return buildItem(ItemBuildContext.of(player));
|
||||
}
|
||||
|
||||
default Item<I> buildItem(ItemBuildContext context) {
|
||||
return buildItem(context, 1);
|
||||
}
|
||||
|
||||
I buildItemStack(ItemBuildContext context, int count);
|
||||
|
||||
default I buildItemStack(ItemBuildContext context) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
@@ -35,12 +34,6 @@ public interface CustomItem<I> extends BuildableItem<I> {
|
||||
return settings().tags().contains(tag);
|
||||
}
|
||||
|
||||
default Item<I> buildItem(Player player) {
|
||||
return buildItem(ItemBuildContext.of(player));
|
||||
}
|
||||
|
||||
Item<I> buildItem(ItemBuildContext context);
|
||||
|
||||
void execute(PlayerOptionalContext context, EventTrigger trigger);
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -24,6 +24,8 @@ public interface ItemManager<T> extends Manageable, ModelGenerator {
|
||||
|
||||
void registerDataType(Function<Object, ItemDataModifier<T>> factory, String... alias);
|
||||
|
||||
Function<Object, ItemDataModifier<T>> getDataType(String key);
|
||||
|
||||
Map<Key, Equipment> equipments();
|
||||
|
||||
ConfigParser[] parsers();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.core.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -16,11 +15,6 @@ public abstract class AbstractGroupedRecipe<T> implements FixedResultRecipe<T> {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T assemble(RecipeInput input, ItemBuildContext context) {
|
||||
return this.result(context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String group() {
|
||||
return group;
|
||||
|
||||
@@ -47,11 +47,6 @@ public class CustomBrewingRecipe<T> implements FixedResultRecipe<T> {
|
||||
return this.container.test(brewingInput.container()) && this.ingredient.test(brewingInput.ingredient());
|
||||
}
|
||||
|
||||
@Override
|
||||
public T assemble(RecipeInput input, ItemBuildContext context) {
|
||||
return this.result(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Ingredient<T>> ingredientsInUse() {
|
||||
List<Ingredient<T>> ingredients = new ArrayList<>();
|
||||
|
||||
@@ -1,11 +1,74 @@
|
||||
package net.momirealms.craftengine.core.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.core.item.BuildableItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
public record CustomRecipeResult<T>(BuildableItem<T> item, int count) {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public record CustomRecipeResult<T>(BuildableItem<T> item, int count, PostProcessor<T>[] postProcessors) {
|
||||
|
||||
public T buildItemStack(ItemBuildContext context) {
|
||||
return item.buildItemStack(context, count);
|
||||
Item<T> builtItem = this.item.buildItem(context, count);
|
||||
if (this.postProcessors != null) {
|
||||
for (PostProcessor<T> postProcessor : this.postProcessors) {
|
||||
builtItem = postProcessor.process(builtItem, context);
|
||||
}
|
||||
}
|
||||
return builtItem.getItem();
|
||||
}
|
||||
|
||||
static {
|
||||
registerPostProcessorType(Key.of("apply_data"), args -> {
|
||||
List<ItemDataModifier<?>> modifiers = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> entry : args.entrySet()) {
|
||||
Optional.ofNullable(CraftEngine.instance().itemManager().getDataType(entry.getKey())).ifPresent(it -> {
|
||||
modifiers.add(it.apply(entry.getValue()));
|
||||
});
|
||||
}
|
||||
return new ApplyItemDataProcessor<>(modifiers.toArray(new ItemDataModifier[0]));
|
||||
});
|
||||
}
|
||||
|
||||
public static void registerPostProcessorType(Key id, PostProcessor.Type<?> type) {
|
||||
((WritableRegistry<PostProcessor.Type<?>>) BuiltInRegistries.RECIPE_POST_PROCESSOR_TYPE).register(ResourceKey.create(Registries.RECIPE_POST_PROCESSOR_TYPE.location(), id), type);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PostProcessor<T> {
|
||||
|
||||
Item<T> process(Item<T> item, ItemBuildContext context);
|
||||
|
||||
interface Type<T> {
|
||||
|
||||
PostProcessor<T> create(Map<String, Object> args);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ApplyItemDataProcessor<T> implements PostProcessor<T> {
|
||||
private final ItemDataModifier<T>[] modifiers;
|
||||
|
||||
public ApplyItemDataProcessor(ItemDataModifier<T>[] modifiers) {
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<T> process(Item<T> item, ItemBuildContext context) {
|
||||
for (ItemDataModifier<T> modifier : this.modifiers) {
|
||||
item.apply(modifier, context);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ public class CustomSmithingTransformRecipe<T> implements FixedResultRecipe<T> {
|
||||
public static class ItemDataProcessors {
|
||||
public static final Key KEEP_COMPONENTS = Key.of("craftengine:keep_components");
|
||||
public static final Key KEEP_TAGS = Key.of("craftengine:keep_tags");
|
||||
public static final Key APPLY_DATA = Key.of("craftengine:apply_data");
|
||||
|
||||
static {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package net.momirealms.craftengine.core.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
|
||||
|
||||
public interface FixedResultRecipe<T> extends Recipe<T> {
|
||||
|
||||
T result(ItemBuildContext context);
|
||||
|
||||
CustomRecipeResult<T> result();
|
||||
|
||||
@Override
|
||||
default T assemble(RecipeInput input, ItemBuildContext context) {
|
||||
return this.result(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ public interface RecipeFactory<T> {
|
||||
return new CustomRecipeResult(
|
||||
CraftEngine.instance().itemManager().getBuildableItem(Key.of(id)).orElseThrow(
|
||||
() -> new LocalizedResourceConfigException("warning.config.recipe.invalid_result", id)),
|
||||
count
|
||||
count,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomRecipeResult;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipe;
|
||||
@@ -74,6 +75,7 @@ public class BuiltInRegistries {
|
||||
public static final Registry<SlotDisplay.Type> SLOT_DISPLAY_TYPE = createConstantBoundRegistry(Registries.SLOT_DISPLAY_TYPE);
|
||||
public static final Registry<RecipeDisplay.Type> RECIPE_DISPLAY_TYPE = createConstantBoundRegistry(Registries.RECIPE_DISPLAY_TYPE);
|
||||
public static final Registry<LegacyRecipe.Type> LEGACY_RECIPE_TYPE = createConstantBoundRegistry(Registries.LEGACY_RECIPE_TYPE);
|
||||
public static final Registry<CustomRecipeResult.ApplyItemDataProcessor.Type<?>> RECIPE_POST_PROCESSOR_TYPE = createConstantBoundRegistry(Registries.RECIPE_POST_PROCESSOR_TYPE);
|
||||
|
||||
private static <T> Registry<T> createConstantBoundRegistry(ResourceKey<? extends Registry<T>> key) {
|
||||
return new ConstantBoundRegistry<>(key);
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomRecipeResult;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipe;
|
||||
@@ -42,7 +43,6 @@ import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
public class Registries {
|
||||
public static final Key ROOT_REGISTRY = Key.withDefaultNamespace("root");
|
||||
public static final ResourceKey<Registry<CustomBlock>> BLOCK = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block"));
|
||||
public static final ResourceKey<Registry<Key>> OPTIMIZED_ITEM_ID = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("optimized_item_id"));
|
||||
public static final ResourceKey<Registry<PropertyFactory>> PROPERTY_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("property_factory"));
|
||||
public static final ResourceKey<Registry<BlockBehaviorFactory>> BLOCK_BEHAVIOR_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block_behavior_factory"));
|
||||
public static final ResourceKey<Registry<ItemBehaviorFactory>> ITEM_BEHAVIOR_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("item_behavior_factory"));
|
||||
@@ -77,4 +77,5 @@ public class Registries {
|
||||
public static final ResourceKey<Registry<SlotDisplay.Type>> SLOT_DISPLAY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("slot_display_type"));
|
||||
public static final ResourceKey<Registry<RecipeDisplay.Type>> RECIPE_DISPLAY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_display_type"));
|
||||
public static final ResourceKey<Registry<LegacyRecipe.Type>> LEGACY_RECIPE_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("legacy_recipe_type"));
|
||||
public static final ResourceKey<Registry<CustomRecipeResult.ApplyItemDataProcessor.Type<?>>> RECIPE_POST_PROCESSOR_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_post_processor_type"));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||
PACK_FORMATS.put(1_21_04, 46);
|
||||
PACK_FORMATS.put(1_21_05, 55);
|
||||
PACK_FORMATS.put(1_21_06, 63);
|
||||
PACK_FORMATS.put(1_21_07, 64); // TODO 1.21.7-rc2
|
||||
PACK_FORMATS.put(1_21_07, 64);
|
||||
PACK_FORMATS.put(1_21_08, 64);
|
||||
PACK_FORMATS.put(1_99_99, 1000);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,5 +18,6 @@ public final class MinecraftVersions {
|
||||
public static final MinecraftVersion V1_21_5 = new MinecraftVersion("1.21.5");
|
||||
public static final MinecraftVersion V1_21_6 = new MinecraftVersion("1.21.6");
|
||||
public static final MinecraftVersion V1_21_7 = new MinecraftVersion("1.21.7");
|
||||
public static final MinecraftVersion V1_21_8 = new MinecraftVersion("1.21.8");
|
||||
public static final MinecraftVersion FUTURE = new MinecraftVersion("1.99.99");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public class VersionHelper {
|
||||
private static final boolean v1_21_5;
|
||||
private static final boolean v1_21_6;
|
||||
private static final boolean v1_21_7;
|
||||
private static final boolean v1_21_8;
|
||||
|
||||
static {
|
||||
try (InputStream inputStream = Class.forName("net.minecraft.obfuscate.DontObfuscate").getResourceAsStream("/version.json")) {
|
||||
@@ -64,6 +65,7 @@ public class VersionHelper {
|
||||
v1_21_5 = version >= 12105;
|
||||
v1_21_6 = version >= 12106;
|
||||
v1_21_7 = version >= 12107;
|
||||
v1_21_8 = version >= 12108;
|
||||
|
||||
majorVersion = major;
|
||||
minorVersion = minor;
|
||||
@@ -215,4 +217,8 @@ public class VersionHelper {
|
||||
public static boolean isOrAbove1_21_7() {
|
||||
return v1_21_7;
|
||||
}
|
||||
|
||||
public static boolean isOrAbove1_21_8() {
|
||||
return v1_21_8;
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,17 @@ org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=0.0.60.2
|
||||
project_version=0.0.60.3
|
||||
config_version=42
|
||||
lang_version=22
|
||||
project_group=net.momirealms
|
||||
latest_supported_version=1.21.7
|
||||
latest_supported_version=1.21.8
|
||||
|
||||
# Supported languages
|
||||
supported_languages=en,zh_cn,zh_tw,es,tr,de,ru_ru
|
||||
|
||||
# Dependency settings
|
||||
paper_version=1.21.7
|
||||
paper_version=1.21.8
|
||||
jetbrains_annotations_version=26.0.2
|
||||
slf4j_version=2.0.17
|
||||
log4j_version=2.24.3
|
||||
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.4
|
||||
anti_grief_version=0.18
|
||||
nms_helper_version=1.0.34
|
||||
nms_helper_version=1.0.36
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.31.23
|
||||
|
||||
Reference in New Issue
Block a user