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

Merge pull request #158 from jhqwqmc/dev

feat(entity): 添加自定义三叉戟
This commit is contained in:
XiaoMoMi
2025-05-10 19:06:45 +08:00
committed by GitHub
15 changed files with 350 additions and 18 deletions

View File

@@ -0,0 +1,12 @@
package net.momirealms.craftengine.bukkit.entity.data;
import net.momirealms.craftengine.bukkit.util.Reflections;
public class ThrowableItemProjectileData<T> extends BaseEntityData<T> {
public static final ThrowableItemProjectileData<Object> ItemStack = new ThrowableItemProjectileData<>(8, EntityDataValue.Serializers$ITEM_STACK, Reflections.instance$ItemStack$Air);
public ThrowableItemProjectileData(int id, Object serializer, T defaultValue) {
super(id, serializer, defaultValue);
}
}

View File

@@ -309,7 +309,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
Object enchant = item.getComponent(ComponentTypes.ENCHANTMENTS);
try {
Map<String, Integer> map = EnchantmentUtils.toMap(enchant);
map.put(enchantment.toString(), enchantment.level());
map.put(enchantment.id().toString(), enchantment.level());
item.setJavaComponent(ComponentTypes.ENCHANTMENTS, map);
} catch (ReflectiveOperationException e) {
plugin.logger().warn("Failed to add enchantment", e);
@@ -321,7 +321,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
Object enchant = item.getComponent(ComponentTypes.STORED_ENCHANTMENTS);
try {
Map<String, Integer> map = EnchantmentUtils.toMap(enchant);
map.put(enchantment.toString(), enchantment.level());
map.put(enchantment.id().toString(), enchantment.level());
item.setJavaComponent(ComponentTypes.STORED_ENCHANTMENTS, map);
} catch (ReflectiveOperationException e) {
plugin.logger().warn("Failed to add stored enchantment", e);

View File

@@ -198,9 +198,9 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
return;
}
}
item.add(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level()), "Enchantments");
item.add(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level()), "Enchantments");
} else {
item.set(List.of(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level())), "Enchantments");
item.set(List.of(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level())), "Enchantments");
}
}
@@ -214,9 +214,9 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
return;
}
}
item.add(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level()), "StoredEnchantments");
item.add(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level()), "StoredEnchantments");
} else {
item.set(List.of(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level())), "StoredEnchantments");
item.set(List.of(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level())), "StoredEnchantments");
}
}

View File

@@ -1,15 +1,35 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.util.CustomTridentUtils;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.standard.*;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
public class TestCommand extends BukkitCommandFeature<CommandSender> {
@@ -18,14 +38,29 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
}
@Override
@SuppressWarnings("deprecation")
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.senderType(Player.class)
.required("text", StringParser.greedyStringParser())
.required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
@Override
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
return CompletableFuture.completedFuture(plugin().itemManager().cachedSuggestions());
}
}))
.required("displayType", ByteParser.byteParser((byte) 0, (byte) 8))
.required("translation", StringParser.stringParser())
.required("rotationLeft", StringParser.stringParser())
.handler(context -> {
String text = "<red><arg:1:0912012><papi:player_name></red>";
PlayerOptionalContext context1 = PlayerOptionalContext.of(plugin().adapt(context.sender()), ContextHolder.builder());
plugin().senderFactory().wrap(context.sender()).sendMessage(AdventureHelper.customMiniMessage().deserialize(text, context1.tagResolvers()));
Player player = context.sender();
NamespacedKey namespacedKey = context.get("id");
ItemStack item = new ItemStack(Material.TRIDENT);
item.editMeta((meta) -> {
Item<ItemStack> ceItem = BukkitItemManager.instance().createWrappedItem(Key.of(namespacedKey.asString()), null);
Optional<Integer> customModelData = ceItem.customModelData();
customModelData.ifPresent(meta::setCustomModelData);
});
player.getInventory().addItem(item);
});
}

View File

@@ -152,6 +152,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, Reflections.clazz$ServerboundLoginAcknowledgedPacket);
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket);
registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, Reflections.clazz$ClientboundEntityEventPacket);
registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY_ALL, Reflections.clazz$ClientboundMoveEntityPacket$PosRot);
registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());

View File

@@ -35,6 +35,7 @@ import net.momirealms.craftengine.core.plugin.network.ConnectionState;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.BlockHitResult;
import net.momirealms.craftengine.core.world.BlockPos;
@@ -1607,16 +1608,22 @@ public class PacketConsumers {
if (furniture != null) {
event.setCancelled(true);
}
} else if (entityType == Reflections.instance$EntityType$TRIDENT) {
CustomTridentUtils.handleCustomTrident(user, event, packet);
}
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e);
}
};
// 1.21.3+
// 1.21.2+
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SYNC_ENTITY_POSITION = (user, event, packet) -> {
try {
int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet);
if (user.tridentView().containsKey(entityId)) {
event.replacePacket(CustomTridentUtils.buildCustomTridentPositionSync(packet, entityId));
return;
}
if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) {
event.setCancelled(true);
}
@@ -1645,6 +1652,11 @@ public class PacketConsumers {
int entityId = intList.getInt(i);
user.entityView().remove(entityId);
List<Integer> entities = user.furnitureView().remove(entityId);
SchedulerTask task = user.tridentTaskView().remove(entityId);
if (task != null) {
task.cancel();
}
user.tridentView().remove(entityId);
if (entities == null) continue;
for (int subEntityId : entities) {
isChange = true;
@@ -2000,6 +2012,16 @@ public class PacketConsumers {
try {
FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt();
if (user.tridentView().containsKey(id)) {
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
List<Object> newPackedItems = CustomTridentUtils.buildCustomTridentSetEntityDataPacket(user, packedItems, id);
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(newPackedItems, buf);
return;
}
Object entityType = user.entityView().get(id);
if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) {
boolean isChanged = false;
@@ -2318,4 +2340,15 @@ public class PacketConsumers {
CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e);
}
};
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_ENTITY_ALL = (user, event, packet) -> {
try {
int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet);
if (user.tridentView().containsKey(entityId)) {
event.replacePacket(CustomTridentUtils.buildCustomTridentMove(packet, entityId));
}
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$PosRot", e);
}
};
}

View File

@@ -20,6 +20,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
@@ -93,6 +94,8 @@ public class BukkitServerPlayer extends Player {
// for better fake furniture visual sync
private final Map<Integer, List<Integer>> furnitureView = new ConcurrentHashMap<>();
private final Map<Integer, Object> entityTypeView = new ConcurrentHashMap<>();
private final Map<Integer, List<Object>> tridentView = new ConcurrentHashMap<>();
private final Map<Integer, SchedulerTask> addTridentPacketView = new ConcurrentHashMap<>();
public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) {
this.channel = channel;
@@ -737,6 +740,16 @@ public class BukkitServerPlayer extends Player {
return this.entityTypeView;
}
@Override
public Map<Integer, List<Object>> tridentView() {
return this.tridentView;
}
@Override
public Map<Integer, SchedulerTask> tridentTaskView() {
return this.addTridentPacketView;
}
public void setResendSound() {
resentSoundTick = gameTicks();
}

View File

@@ -0,0 +1,163 @@
package net.momirealms.craftengine.bukkit.util;
import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.network.NMSPacketEvent;
import net.momirealms.craftengine.core.entity.CustomTrident;
import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.item.Enchantment;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MCUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Trident;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class CustomTridentUtils {
public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) {
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
Trident trident = getTridentById(user, entityId);
if (trident == null) return;
World world = trident.getWorld();
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(trident);
Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity);
Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity);
if (notCustomTrident(trident)) return;
Object newPacket = modifyCustomTridentPacket(packet, entityId);
List<Object> itemDisplayValues = buildEntityDataValues(trident);
user.tridentView().put(entityId, itemDisplayValues);
user.sendPacket(newPacket, true);
user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true);
event.setCancelled(true);
if (serverEntity != null) {
// 这里直接暴力更新
SchedulerTask task = CraftEngine.instance().scheduler().asyncRepeating(() -> {
FastNMS.INSTANCE.method$ServerEntity$sendChanges(serverEntity);
if (canSpawnParticle(nmsEntity)) {
world.spawnParticle(ParticleUtils.getParticle("BUBBLE"), trident.getLocation(), 1, 0, 0, 0, 0);
}
}, 0, 5, TimeUnit.MILLISECONDS);
user.tridentTaskView().put(entityId, task);
}
}
private static boolean canSpawnParticle(Object nmsEntity) {
if (!FastNMS.INSTANCE.field$AbstractArrow$wasTouchingWater(nmsEntity)) return false;
return !FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity);
}
@Nullable
public static Trident getTridentById(NetWorkUser user, int entityId) {
Player player = (Player) user.platformPlayer();
Entity entity = FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId);
if (entity instanceof Trident trident) return trident;
return null;
}
public static boolean notCustomTrident(Trident trident) {
if (trident == null) return true;
Optional<CustomItem<ItemStack>> customItem = BukkitItemManager.instance().wrap(trident.getItemStack()).getCustomItem();
return customItem.map(itemStackCustomItem -> itemStackCustomItem.settings().customTrident() == null).orElse(true);
}
public static Object modifyCustomTridentPacket(Object packet, int entityId) {
UUID uuid = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$uuid(packet);
double x = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$x(packet);
double y = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$y(packet);
double z = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$z(packet);
float yRot = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$yRot(packet);
float xRot = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$xRot(packet);
Object type = Reflections.instance$EntityType$ITEM_DISPLAY;
int data = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$data(packet);
double xa = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$xa(packet);
double ya = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$ya(packet);
double za = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$za(packet);
double yHeadRot = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$yHeadRot(packet);
return FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entityId, uuid, x, y, z,
MCUtils.clamp(-xRot, -90.0F, 90.0F), -yRot,
type, data, FastNMS.INSTANCE.constructor$Vec3(xa, ya, za), yHeadRot
);
}
public static List<Object> buildEntityDataValues(Trident trident) {
List<Object> itemDisplayValues = new ArrayList<>();
ItemStack itemStack = trident.getItemStack();
Optional<CustomItem<ItemStack>> customItem = BukkitItemManager.instance().wrap(itemStack).getCustomItem();
if (customItem.isEmpty()) return itemDisplayValues;
CustomTrident customTrident = customItem.get().settings().customTrident();
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(customTrident.customTridentItemId(), null);
itemStack.getEnchantments().forEach((enchantment, level) -> item.addEnchantment(new Enchantment(Key.of(enchantment.getKey().toString()), level)));
ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(-1, itemDisplayValues);
ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(customTrident.translation(), itemDisplayValues);
ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(customTrident.rotationLefts(), itemDisplayValues);
if (VersionHelper.isOrAbove1_20_2()) {
ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues);
ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues);
} else {
ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues);
}
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues);
ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(customTrident.displayType(), itemDisplayValues);
return itemDisplayValues;
}
public static Object buildCustomTridentPositionSync(Object packet, int entityId) {
Object positionMoveRotation = FastNMS.INSTANCE.field$ClientboundEntityPositionSyncPacket$values(packet);
boolean onGround = FastNMS.INSTANCE.field$ClientboundEntityPositionSyncPacket$onGround(packet);
Object position = FastNMS.INSTANCE.field$PositionMoveRotation$position(positionMoveRotation);
Object deltaMovement = FastNMS.INSTANCE.field$PositionMoveRotation$deltaMovement(positionMoveRotation);
float yRot = FastNMS.INSTANCE.field$PositionMoveRotation$yRot(positionMoveRotation);
float xRot = FastNMS.INSTANCE.field$PositionMoveRotation$xRot(positionMoveRotation);
Object newPositionMoveRotation = FastNMS.INSTANCE.constructor$PositionMoveRotation(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F));
return FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(entityId, newPositionMoveRotation, onGround);
}
public static Object buildCustomTridentMove(Object packet, int entityId) {
short xa = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$xa(packet);
short ya = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$ya(packet);
short za = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$za(packet);
float xRot = MCUtils.unpackDegrees(FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$xRot(packet));
float yRot = MCUtils.unpackDegrees(FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$yRot(packet));
boolean onGround = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$onGround(packet);
return FastNMS.INSTANCE.constructor$ClientboundMoveEntityPacket$PosRot(
entityId, xa, ya, za,
MCUtils.packDegrees(-yRot), MCUtils.packDegrees(MCUtils.clamp(-xRot, -90.0F, 90.0F)),
onGround
);
}
public static List<Object> buildCustomTridentSetEntityDataPacket(NetWorkUser user, List<Object> packedItems, int entityId) {
List<Object> newPackedItems = new ArrayList<>();
for (Object packedItem : packedItems) {
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId < 8) {
newPackedItems.add(packedItem);
}
}
List<Object> newData = user.tridentView().getOrDefault(entityId, List.of());
if (newData.isEmpty()) {
Trident trident = getTridentById(user, entityId);
if (notCustomTrident(trident)) return newPackedItems;
newData = buildEntityDataValues(trident);
user.tridentView().put(entityId, newData);
}
newPackedItems.addAll(newData);
return newPackedItems;
}
}

View File

@@ -12,6 +12,7 @@ public class ParticleUtils {
return switch (particle) {
case "REDSTONE" -> Particle.valueOf("DUST");
case "VILLAGER_HAPPY", "HAPPY_VILLAGER" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "HAPPY_VILLAGER" : "VILLAGER_HAPPY");
case "BUBBLE" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "BUBBLE" : "WATER_BUBBLE");
default -> Particle.valueOf(particle);
};
}

View File

@@ -558,7 +558,6 @@ public class Reflections {
)
);
@Deprecated
public static final Field field$ClientboundAddEntityPacket$type = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$ClientboundAddEntityPacket, clazz$EntityType, 0
@@ -3810,6 +3809,8 @@ public class Reflections {
public static final Object instance$EntityType$INTERACTION;
public static final Object instance$EntityType$SHULKER;
public static final Object instance$EntityType$OAK_BOAT;
public static final Object instance$EntityType$TRIDENT;
public static final Object instance$EntityType$SNOWBALL;
static {
try {
@@ -3829,6 +3830,10 @@ public class Reflections {
instance$EntityType$ARMOR_STAND = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, armorStand);
Object oakBoat = VersionHelper.isOrAbove1_21_2() ? FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "oak_boat") : FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "boat");
instance$EntityType$OAK_BOAT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, oakBoat);
Object trident = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "trident");
instance$EntityType$TRIDENT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, trident);
Object snowball = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "snowball");
instance$EntityType$SNOWBALL = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, snowball);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
@@ -3979,7 +3984,7 @@ public class Reflections {
)
);
// 1.21.3+
// 1.21.2+
public static final Class<?> clazz$ClientboundEntityPositionSyncPacket =
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundEntityPositionSyncPacket")
@@ -6098,6 +6103,10 @@ public class Reflections {
)
);
public static final Constructor<?> constructor$ClientboundMoveEntityPacket$PosRot = requireNonNull(
ReflectionUtils.getTheOnlyConstructor(clazz$ClientboundMoveEntityPacket$PosRot)
);
public static final Class<?> clazz$ClientboundRotateHeadPacket = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"network.protocol.game.PacketPlayOutEntityHeadRotation",
@@ -6395,14 +6404,18 @@ public class Reflections {
);
public static final int instance$EntityType$BLOCK_DISPLAY$registryId;
public static final int instance$EntityType$ITEM_DISPLAY$registryId;
public static final int instance$EntityType$TEXT_DISPLAY$registryId;
public static final int instance$EntityType$FALLING_BLOCK$registryId;
public static final int instance$EntityType$TRIDENT$registryId;
static {
try {
instance$EntityType$BLOCK_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$BLOCK_DISPLAY);
instance$EntityType$ITEM_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$ITEM_DISPLAY);
instance$EntityType$TEXT_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$TEXT_DISPLAY);
instance$EntityType$FALLING_BLOCK$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$FALLING_BLOCK);
instance$EntityType$TRIDENT$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$TRIDENT);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -6618,4 +6631,5 @@ public class Reflections {
BukkitReflectionUtils.assembleCBClass("block.CraftBlockStates$BlockEntityStateFactory")
)
);
}

View File

@@ -0,0 +1,8 @@
package net.momirealms.craftengine.core.entity;
import net.momirealms.craftengine.core.util.Key;
import org.joml.Quaternionf;
import org.joml.Vector3f;
public record CustomTrident(Key customTridentItemId, Byte displayType, Vector3f translation, Quaternionf rotationLefts) {
}

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.core.item;
import net.momirealms.craftengine.core.entity.CustomTrident;
import net.momirealms.craftengine.core.item.modifier.EquippableModifier;
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
import net.momirealms.craftengine.core.pack.misc.EquipmentGeneration;
@@ -9,6 +10,8 @@ import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.*;
import java.util.stream.Collectors;
@@ -22,6 +25,7 @@ public class ItemSettings {
List<AnvilRepairItem> anvilRepairItems = List.of();
boolean renameable = true;
boolean canPlaceRelatedVanillaBlock = false;
CustomTrident customTrident;
private ItemSettings() {}
@@ -50,6 +54,7 @@ public class ItemSettings {
newSettings.anvilRepairItems = settings.anvilRepairItems;
newSettings.renameable = settings.renameable;
newSettings.canPlaceRelatedVanillaBlock = settings.canPlaceRelatedVanillaBlock;
newSettings.customTrident = settings.customTrident;
return newSettings;
}
@@ -65,6 +70,10 @@ public class ItemSettings {
return settings;
}
public CustomTrident customTrident() {
return customTrident;
}
public boolean canPlaceRelatedVanillaBlock() {
return canPlaceRelatedVanillaBlock;
}
@@ -109,6 +118,11 @@ public class ItemSettings {
return this;
}
public ItemSettings customTrident(CustomTrident customTrident) {
this.customTrident = customTrident;
return this;
}
public ItemSettings canPlaceRelatedVanillaBlock(boolean canPlaceRelatedVanillaBlock) {
this.canPlaceRelatedVanillaBlock = canPlaceRelatedVanillaBlock;
return this;
@@ -193,6 +207,14 @@ public class ItemSettings {
boolean bool = (boolean) value;
return settings -> settings.canPlaceRelatedVanillaBlock(bool);
}));
registerFactory("custom-trident", (value -> {
Map<String, Object> args = MiscUtils.castToMap(value, false);
Key customTridentItemId = Key.of(args.get("custom-trident-item").toString());
Byte displayType = Byte.valueOf(args.get("display-type").toString());
Vector3f translation = MiscUtils.getAsVector3f(args.get("translation"), "translation");
Quaternionf rotationLefts = MiscUtils.getAsQuaternionf(args.get("rotation-left"), "rotation-left");
return settings -> settings.customTrident(new CustomTrident(customTridentItemId, displayType, translation, rotationLefts));
}));
}
private static void registerFactory(String id, ItemSettings.Modifier.Factory factory) {

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.network;
import io.netty.channel.Channel;
import net.momirealms.craftengine.core.plugin.Plugin;
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.ApiStatus;
@@ -46,6 +47,10 @@ public interface NetWorkUser {
Map<Integer, Object> entityView();
Map<Integer, List<Object>> tridentView();
Map<Integer, SchedulerTask> tridentTaskView();
boolean clientModEnabled();
void setClientModState(boolean enable);

View File

@@ -184,4 +184,29 @@ public class MCUtils {
}
return next;
}
public static int floor(float value) {
int i = (int) value;
return value < (float)i ? i - 1 : i;
}
public static byte packDegrees(float degrees) {
return (byte)floor(degrees * 256.0F / 360.0F);
}
public static float unpackDegrees(byte degrees) {
return (float)(degrees * 360) / 256.0F;
}
public static int clamp(int value, int min, int max) {
return Math.min(Math.max(value, min), max);
}
public static float clamp(float value, float min, float max) {
return value < min ? min : Math.min(value, max);
}
public static double clamp(double value, double min, double max) {
return value < min ? min : Math.min(value, max);
}
}

View File

@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
ahocorasick_version=0.6.3
snake_yaml_version=2.4
anti_grief_version=0.15
nms_helper_version=0.65.15
nms_helper_version=0.65.17
evalex_version=3.5.0
reactive_streams_version=1.0.4
amazon_awssdk_version=2.31.23