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

Merge pull request #396 from jhqwqmc/dev

完善图腾命令
This commit is contained in:
XiaoMoMi
2025-10-04 20:27:13 +08:00
committed by GitHub
19 changed files with 171 additions and 93 deletions

View File

@@ -16,7 +16,7 @@ public class BetterModelModel extends AbstractExternalModel {
@Override
public void bindModel(AbstractEntity entity) {
org.bukkit.entity.Entity bukkitEntity = (org.bukkit.entity.Entity) entity.literalObject();
org.bukkit.entity.Entity bukkitEntity = (org.bukkit.entity.Entity) entity.platformEntity();
BetterModelUtils.bindModel(bukkitEntity, id());
}
}

View File

@@ -16,7 +16,7 @@ public class ModelEngineModel extends AbstractExternalModel {
@Override
public void bindModel(AbstractEntity entity) {
org.bukkit.entity.Entity bukkitEntity = (org.bukkit.entity.Entity) entity.literalObject();
org.bukkit.entity.Entity bukkitEntity = (org.bukkit.entity.Entity) entity.platformEntity();
ModelEngineUtils.bindModel(bukkitEntity, id());
}
}

View File

@@ -1,6 +1,8 @@
package net.momirealms.craftengine.bukkit.block.behavior;
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
@@ -80,8 +82,8 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
public void onBrokenAfterFall(Object thisBlock, Object[] args) throws Exception {
Object level = args[0];
Object fallingBlockEntity = args[2];
Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity);
if (!BaseEntityData.Silent.get(entityData)) {
BukkitEntity entity = BukkitAdaptors.adapt(FastNMS.INSTANCE.method$Entity$getBukkitEntity(fallingBlockEntity));
if (!entity.getEntityData(BaseEntityData.Silent)) {
Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity);
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return;
@@ -94,16 +96,16 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
}
@Override
public void onLand(Object thisBlock, Object[] args) throws Exception {
public void onLand(Object thisBlock, Object[] args) {
Object fallingBlock = args[4];
Object level = args[0];
Object pos = args[1];
Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlock);
BukkitEntity entity = BukkitAdaptors.adapt(FastNMS.INSTANCE.method$Entity$getBukkitEntity(fallingBlock));
Object blockState = args[2];
int stateId = BlockStateUtils.blockStateToId(blockState);
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
if (!BaseEntityData.Silent.get(entityData)) {
if (!entity.getEntityData(BaseEntityData.Silent)) {
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
if (this.landSound != null) {
world.playBlockSound(Vec3d.atCenterOf(LocationUtils.fromBlockPos(pos)), this.landSound);

View File

@@ -1,8 +1,10 @@
package net.momirealms.craftengine.bukkit.entity;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.EntityUtils;
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.entity.AbstractEntity;
import net.momirealms.craftengine.core.entity.data.EntityData;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.World;
@@ -19,17 +21,17 @@ public class BukkitEntity extends AbstractEntity {
@Override
public double x() {
return literalObject().getX();
return platformEntity().getX();
}
@Override
public double y() {
return literalObject().getY();
return platformEntity().getY();
}
@Override
public double z() {
return literalObject().getZ();
return platformEntity().getZ();
}
@Override
@@ -38,22 +40,22 @@ public class BukkitEntity extends AbstractEntity {
@Override
public int entityID() {
return literalObject().getEntityId();
return platformEntity().getEntityId();
}
@Override
public float xRot() {
return literalObject().getYaw();
return platformEntity().getYaw();
}
@Override
public float yRot() {
return literalObject().getPitch();
return platformEntity().getPitch();
}
@Override
public World world() {
return new BukkitWorld(literalObject().getWorld());
return new BukkitWorld(platformEntity().getWorld());
}
@Override
@@ -62,22 +64,43 @@ public class BukkitEntity extends AbstractEntity {
}
@Override
public org.bukkit.entity.Entity literalObject() {
public org.bukkit.entity.Entity platformEntity() {
return this.entity.get();
}
@Override
public Object serverEntity() {
return FastNMS.INSTANCE.method$CraftEntity$getHandle(platformEntity());
}
@Override
public Key type() {
return EntityUtils.getEntityType(literalObject());
return EntityUtils.getEntityType(platformEntity());
}
@Override
public String name() {
return literalObject().getName();
return platformEntity().getName();
}
@Override
public UUID uuid() {
return literalObject().getUniqueId();
return platformEntity().getUniqueId();
}
@Override
public Object entityData() {
return FastNMS.INSTANCE.field$Entity$entityData(serverEntity());
}
@SuppressWarnings("unchecked")
@Override
public <T> T getEntityData(EntityData<T> data) {
return (T) FastNMS.INSTANCE.method$SynchedEntityData$get(entityData(), data.entityDataAccessor());
}
@Override
public <T> void setEntityData(EntityData<T> data, T value, boolean force) {
FastNMS.INSTANCE.method$SynchedEntityData$set(entityData(), data.entityDataAccessor(), value, force);
}
}

View File

@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
import java.util.Optional;
public class BaseEntityData<T> extends SimpleEntityData<T> {
public class BaseEntityData<T> extends BukkitEntityData<T> {
public static final BaseEntityData<Byte> SharedFlags = new BaseEntityData<>(BaseEntityData.class, EntityDataValue.Serializers$BYTE, (byte) 0);
public static final BaseEntityData<Integer> AirSupply = new BaseEntityData<>(BaseEntityData.class, EntityDataValue.Serializers$INT, 300);
public static final BaseEntityData<Optional<Object>> CustomName = new BaseEntityData<>(BaseEntityData.class, EntityDataValue.Serializers$OPTIONAL_COMPONENT, Optional.empty());

View File

@@ -2,15 +2,16 @@ package net.momirealms.craftengine.bukkit.entity.data;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.core.entity.data.ClassTreeIdRegistry;
import net.momirealms.craftengine.core.entity.data.EntityData;
public class SimpleEntityData<T> implements EntityData<T> {
public class BukkitEntityData<T> implements EntityData<T> {
public static final ClassTreeIdRegistry ID_REGISTRY = new ClassTreeIdRegistry();
private final int id;
private final Object serializer;
private final T defaultValue;
private final Object entityDataAccessor;
public SimpleEntityData(Class<?> clazz, Object serializer, T defaultValue) {
public BukkitEntityData(Class<?> clazz, Object serializer, T defaultValue) {
this.id = ID_REGISTRY.define(clazz);
this.serializer = serializer;
this.defaultValue = defaultValue;
@@ -36,4 +37,9 @@ public class SimpleEntityData<T> implements EntityData<T> {
public Object entityDataAccessor() {
return entityDataAccessor;
}
@Override
public Object create(Object entityDataAccessor, Object value) {
return EntityDataValue.create(entityDataAccessor, value);
}
}

View File

@@ -1,40 +0,0 @@
package net.momirealms.craftengine.bukkit.entity.data;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import java.util.List;
public interface EntityData<T> {
Object serializer();
int id();
T defaultValue();
Object entityDataAccessor();
default Object createEntityDataIfNotDefaultValue(T value) {
if (defaultValue().equals(value)) return null;
return EntityDataValue.create(id(), serializer(), entityDataAccessor(), value);
}
default void addEntityDataIfNotDefaultValue(T value, List<Object> list) {
if (!defaultValue().equals(value)) {
list.add(EntityDataValue.create(id(), serializer(), entityDataAccessor(), value));
}
}
default void addEntityData(T value, List<Object> list) {
list.add(EntityDataValue.create(id(), serializer(), entityDataAccessor(), value));
}
@SuppressWarnings("unchecked")
default T get(Object entityData) {
return (T) FastNMS.INSTANCE.method$SynchedEntityData$get(entityData, entityDataAccessor());
}
static <T> EntityData<T> of(Class<?> clazz, Object serializer, T defaultValue) {
return new SimpleEntityData<>(clazz, serializer, defaultValue);
}
}

View File

@@ -99,7 +99,7 @@ public class EntityDataValue {
throw new IllegalAccessError("Utility class");
}
public static Object create(int id, Object serializer, Object entityDataAccessor, Object value) {
public static Object create(Object entityDataAccessor, Object value) {
return FastNMS.INSTANCE.method$SynchedEntityData$DataValue$create(entityDataAccessor, value);
}
}

View File

@@ -3,7 +3,10 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MSoundEvents;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.bukkit.util.PlayerUtils;
@@ -34,11 +37,13 @@ import org.incendo.cloud.parser.standard.FloatParser;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
public static final Object FIX_TOTEM_SOUND_PACKET = FastNMS.INSTANCE.constructor$ClientboundSoundPacket(FastNMS.INSTANCE.method$Holder$direct(MSoundEvents.TOTEM_USE), CoreReflections.instance$SoundSource$MUSIC, 0, Integer.MIN_VALUE, 0, 0, 0, 0);
public TotemAnimationCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
super(commandManager, plugin);
@@ -85,17 +90,21 @@ public class TotemAnimationCommand extends BukkitCommandFeature<CommandSender> {
}
boolean removeSound = context.flags().hasFlag("no-sound");
MultiplePlayerSelector selector = context.get("players");
for (Player player : selector.values()) {
Collection<Player> players = selector.values();
for (Player player : players) {
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player);
Item<ItemStack> item = customItem.buildItem(serverPlayer);
if (VersionHelper.isOrAbove1_21_2()) {
item.setJavaComponent(ComponentTypes.DEATH_PROTECTION, Map.of());
}
// TODO 存在第一次进服 未正确移除图腾声音的问题
PlayerUtils.sendTotemAnimation(serverPlayer, item, soundData, removeSound);
}
// TODO 消息提示
if (players.size() == 1) {
handleFeedback(context, MessageConstants.COMMAND_TOTEM_SUCCESS_SINGLE, Component.text(namespacedKey.toString()), Component.text(players.iterator().next().getName()));
} else if (players.size() > 1) {
handleFeedback(context, MessageConstants.COMMAND_TOTEM_SUCCESS_MULTIPLE, Component.text(namespacedKey.toString()), Component.text(players.size()));
}
});
}

View File

@@ -36,6 +36,7 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.command.feature.TotemAnimationCommand;
import net.momirealms.craftengine.bukkit.plugin.injector.ProtectedFieldVisitor;
import net.momirealms.craftengine.bukkit.plugin.network.handler.*;
import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIds1_20;
@@ -423,6 +424,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
player.getScheduler().runAtFixedRate(plugin.javaPlugin(), (t) -> user.tick(),
() -> {}, 1, 1);
}
user.sendPacket(TotemAnimationCommand.FIX_TOTEM_SOUND_PACKET, false);
}
}
@@ -2385,7 +2387,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
}
}
@SuppressWarnings("all")
@SuppressWarnings({"deprecation", "all"})
public HoverEvent.ShowItem replaceShowItem(HoverEvent.ShowItem showItem, BukkitServerPlayer player) {
Object nmsItemStack;
if (VersionHelper.COMPONENT_RELEASE) {

View File

@@ -8,10 +8,13 @@ package net.momirealms.craftengine.bukkit.plugin.reflection.leaves;
//import java.lang.reflect.Field;
//import java.util.Optional;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ReflectionUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Optional;
// TODO API 太新了需要1.21.8,目前先采用其他方式解决假人问题
public final class LeavesReflections {
@@ -36,14 +39,21 @@ public final class LeavesReflections {
// public static final Field field$BotRemoveEvent$handlers = Optional.ofNullable(clazz$BotRemoveEvent)
// .map(it -> ReflectionUtils.getDeclaredField(it, HandlerList.class, 0))
// .orElse(null);
public static final Class<?> clazz$ServerBot = ReflectionUtils.getClazz("org.leavesmc.leaves.bot.ServerBot");
//
//
// public static final Class<?> clazz$ServerBot = ReflectionUtils.getClazz("org.leavesmc.leaves.bot.ServerBot");
// 注入BotList来实现全版本的监听
public static final Class<?> clazz$BotList = ReflectionUtils.getClazz("org.leavesmc.leaves.bot.BotList");
public static final Class<?> clazz$BotList = MiscUtils.requireNonNullIf(
ReflectionUtils.getClazz("org.leavesmc.leaves.bot.BotList"),
VersionHelper.isLeaves()
);
public static final Field field$BotList$INSTANCE = ReflectionUtils.getDeclaredField(clazz$BotList, clazz$BotList, 0);
public static final Field field$BotList$INSTANCE = Optional.ofNullable(clazz$BotList)
.map(c -> ReflectionUtils.getDeclaredField(c, c, 0))
.orElse(null);
public static final Field field$BotList$bots = ReflectionUtils.getDeclaredField(clazz$BotList, List.class, 0);
public static final Field field$BotList$bots = Optional.ofNullable(clazz$BotList)
.map(c -> ReflectionUtils.getDeclaredField(c, List.class, 0))
.orElse(null);
}

View File

@@ -5,22 +5,15 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
public final class MSoundEvents {
private MSoundEvents() {}
public static final Object EMPTY;
public static final Object TRIDENT_RIPTIDE_1;
public static final Object TRIDENT_RIPTIDE_2;
public static final Object TRIDENT_RIPTIDE_3;
public static final Object TRIDENT_THROW;
public static final Object EMPTY = getById("intentionally_empty");
public static final Object TRIDENT_RIPTIDE_1 = getById("item.trident_riptide_1");
public static final Object TRIDENT_RIPTIDE_2 = getById("item.trident_riptide_2");
public static final Object TRIDENT_RIPTIDE_3 = getById("item.trident.riptide_3");
public static final Object TRIDENT_THROW = getById("item.trident.throw");
public static final Object TOTEM_USE = getById("item.totem.use");
private static Object getById(String id) {
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.SOUND_EVENT, rl);
}
static {
EMPTY = getById("intentionally_empty");
TRIDENT_RIPTIDE_1 = getById("item.trident_riptide_1");
TRIDENT_RIPTIDE_2 = getById("item.trident_riptide_2");
TRIDENT_RIPTIDE_3 = getById("item.trident.riptide_3");
TRIDENT_THROW = getById("item.trident.throw");
}
}

View File

@@ -8,15 +8,13 @@ import io.netty.channel.ChannelHandler;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
import net.momirealms.craftengine.bukkit.block.entity.BlockEntityHolder;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.*;
import net.momirealms.craftengine.core.entity.data.EntityData;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.gui.CraftEngineGUIHolder;
import net.momirealms.craftengine.bukkit.plugin.network.payload.DiscardedPayload;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
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;
@@ -943,10 +941,15 @@ public class BukkitServerPlayer extends Player {
}
@Override
public org.bukkit.entity.Player literalObject() {
public org.bukkit.entity.Player platformEntity() {
return platformPlayer();
}
@Override
public Object serverEntity() {
return serverPlayer();
}
@Override
public Map<Integer, EntityPacketHandler> entityPacketHandlers() {
return this.entityTypeView;
@@ -1143,4 +1146,20 @@ public class BukkitServerPlayer extends Player {
DamageType type = Registry.DAMAGE_TYPE.get(KeyUtils.toNamespacedKey(damageType));
this.platformPlayer().damage(amount, DamageSource.builder(type != null ? type : DamageType.GENERIC).build());
}
@Override
public Object entityData() {
return FastNMS.INSTANCE.field$Entity$entityData(serverEntity());
}
@SuppressWarnings("unchecked")
@Override
public <T> T getEntityData(EntityData<T> data) {
return (T) FastNMS.INSTANCE.method$SynchedEntityData$get(entityData(), data.entityDataAccessor());
}
@Override
public <T> void setEntityData(EntityData<T> data, T value, boolean force) {
FastNMS.INSTANCE.method$SynchedEntityData$set(entityData(), data.entityDataAccessor(), value, force);
}
}

View File

@@ -54,6 +54,8 @@ command.search_usage.not_found: "<red>No usage found for this item</red>"
command.search_recipe.no_item: "<red>Please hold an item before running this command</red>"
command.search_usage.no_item: "<red>Please hold an item before running this command</red>"
command.totem_animation.failure.not_totem: "<red>Item '<arg:0>' is not minecraft:totem_of_undying</red>"
commands.totem_animation.success.single: "<white>Played totem animation <arg:0> to <arg:1></white>"
commands.totem_animation.success.multiple: "<white>Played totem animation <arg:0> to <arg:1> players</white>"
command.resource.enable.success: "<white>Enabled resource <arg:0>. Run <click:run_command:/ce reload all><u>/ce reload all</u></click> to apply changes</white>"
command.resource.enable.failure.unknown: "<red>Unknown resource <arg:0></red>"
command.resource.disable.success: "<white>Disabled resource <arg:0>. Run <click:run_command:/ce reload all><u>/ce reload all</u></click> to apply changes</white>"

View File

@@ -54,6 +54,8 @@ command.search_usage.not_found: "<red>找不到此物品的用途</red>"
command.search_recipe.no_item: "<red>请手持物品后再执行此命令</red>"
command.search_usage.no_item: "<red>请手持物品后再执行此命令</red>"
command.totem_animation.failure.not_totem: "<red>'<arg:0>' 不是 totem_of_undying 类型</red>"
commands.totem_animation.success.single: "<white>已将图腾动画<arg:0>播放给<arg:1></white>"
commands.totem_animation.success.multiple: "<white>已将图腾动画<arg:0>播放给<arg:1>名玩家</white>"
command.resource.enable.success: "<white>已启用 <arg:0>. 执行 <click:run_command:/ce reload all><u>/ce reload all</u></click> 以应用更改</white>"
command.resource.enable.failure.unknown: "<red>未知资源 <arg:0></red>"
command.resource.disable.success: "<white>已禁用 <arg:0>. 执行 <click:run_command:/ce reload all><u>/ce reload all</u></click> 以应用更改</white>"

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.entity;
import net.momirealms.craftengine.core.entity.data.EntityData;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.World;
@@ -30,9 +31,21 @@ public interface Entity {
Direction getDirection();
Object literalObject();
Object platformEntity();
Object serverEntity();
String name();
UUID uuid();
Object entityData();
<T> T getEntityData(EntityData<T> entityData);
default <T> void setEntityData(EntityData<T> data, T value) {
setEntityData(data, value, false);
}
<T> void setEntityData(EntityData<T> data, T value, boolean force);
}

View File

@@ -0,0 +1,35 @@
package net.momirealms.craftengine.core.entity.data;
import java.util.List;
public interface EntityData<T> {
Object serializer();
int id();
T defaultValue();
Object entityDataAccessor();
Object create(Object entityDataAccessor, Object value);
default Object createEntityDataIfNotDefaultValue(T value) {
if (defaultValue().equals(value)) return null;
return create(entityDataAccessor(), value);
}
default Object createEntityData(Object value) {
return create(entityDataAccessor(), value);
}
default void addEntityDataIfNotDefaultValue(T value, List<Object> list) {
if (!defaultValue().equals(value)) {
list.add(create(entityDataAccessor(), value));
}
}
default void addEntityData(T value, List<Object> list) {
list.add(create(entityDataAccessor(), value));
}
}

View File

@@ -30,4 +30,6 @@ public interface MessageConstants {
TranslatableComponent.Builder COMMAND_UPLOAD_ON_PROGRESS = Component.translatable().key("command.upload.on_progress");
TranslatableComponent.Builder COMMAND_SEND_RESOURCE_PACK_SUCCESS_SINGLE = Component.translatable().key("command.send_resource_pack.success.single");
TranslatableComponent.Builder COMMAND_SEND_RESOURCE_PACK_SUCCESS_MULTIPLE = Component.translatable().key("command.send_resource_pack.success.multiple");
TranslatableComponent.Builder COMMAND_TOTEM_SUCCESS_SINGLE = Component.translatable().key("commands.totem_animation.success.single");
TranslatableComponent.Builder COMMAND_TOTEM_SUCCESS_MULTIPLE = Component.translatable().key("commands.totem_animation.success.multiple");
}

View File

@@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx1G
# Rule: [major update].[feature update].[bug fix]
project_version=0.0.63.9
config_version=47
lang_version=32
lang_version=33
project_group=net.momirealms
latest_supported_version=1.21.10
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
ahocorasick_version=0.6.3
snake_yaml_version=2.5
anti_grief_version=1.0.2
nms_helper_version=1.0.101
nms_helper_version=1.0.102
evalex_version=3.5.0
reactive_streams_version=1.0.4
amazon_awssdk_version=2.34.5