mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
Merge remote-tracking branch 'upstream/dev' into dev
# Conflicts: # bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java # gradle.properties
This commit is contained in:
@@ -19,6 +19,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.RegistryUtils;
|
||||
@@ -44,7 +45,6 @@ import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -161,8 +161,8 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, list));
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
this.plugin.networkManager().sendPacket(this.plugin.adapt(player), packet);
|
||||
for (BukkitServerPlayer player : this.plugin.networkManager().onlineUsers()) {
|
||||
player.sendPacket(packet, false);
|
||||
}
|
||||
// 如果空,那么新来的玩家就没必要收到更新包了
|
||||
if (list.isEmpty()) {
|
||||
|
||||
@@ -15,12 +15,12 @@ import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.item.setting.FoodData;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Cancellable;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
@@ -33,6 +33,8 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
@@ -49,6 +51,28 @@ public class ItemEventListener implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onInteractEntity(PlayerInteractEntityEvent event) {
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(event.getPlayer());
|
||||
if (serverPlayer == null) return;
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(hand);
|
||||
|
||||
if (itemInHand == null) return;
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||
if (optionalCustomItem.isEmpty()) return;
|
||||
|
||||
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(event.getRightClicked().getLocation()))
|
||||
.withParameter(DirectContextParameters.HAND, hand)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onInteractBlock(PlayerInteractEvent event) {
|
||||
Action action = event.getAction();
|
||||
@@ -62,6 +86,7 @@ public class ItemEventListener implements Listener {
|
||||
}
|
||||
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
if (serverPlayer == null) return;
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
// 如果本tick内主手已被处理,则不处理副手
|
||||
// 这是因为客户端可能会同时发主副手交互包,但实际上只能处理其中一个
|
||||
@@ -329,6 +354,36 @@ public class ItemEventListener implements Listener {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
if (event.getPlayer().getGameMode() != GameMode.CREATIVE) {
|
||||
Key replacement = customItem.settings().consumeReplacement();
|
||||
if (replacement == null) {
|
||||
event.setReplacement(null);
|
||||
} else {
|
||||
ItemStack replacementItem = this.plugin.itemManager().buildItemStack(replacement, this.plugin.adapt(event.getPlayer()));
|
||||
event.setReplacement(replacementItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) return;
|
||||
if (!(event.getEntity() instanceof Player player)) return;
|
||||
ItemStack consumedItem = event.getItem();
|
||||
if (ItemUtils.isEmpty(consumedItem)) return;
|
||||
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(consumedItem);
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||
if (optionalCustomItem.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
FoodData foodData = customItem.settings().foodData();
|
||||
if (foodData == null) return;
|
||||
event.setCancelled(true);
|
||||
int oldFoodLevel = player.getFoodLevel();
|
||||
if (foodData.nutrition() != 0) player.setFoodLevel(MCUtils.clamp(oldFoodLevel + foodData.nutrition(), 0, 20));
|
||||
float oldSaturation = player.getSaturation();
|
||||
if (foodData.saturation() != 0) player.setSaturation(MCUtils.clamp(oldSaturation, 0, 10));
|
||||
}
|
||||
|
||||
private boolean cancelEventIfHasInteraction(PlayerInteractEvent event, BukkitServerPlayer player, InteractionHand hand) {
|
||||
|
||||
@@ -179,6 +179,10 @@ public final class BlockGenerator {
|
||||
if (CoreReflections.clazz$ServerLevel.isInstance(args[levelIndex])) {
|
||||
startNoteBlockChain(args);
|
||||
}
|
||||
} else if (indicator.isTripwire()) {
|
||||
if (CoreReflections.clazz$ServerLevel.isInstance(args[posIndex])) {
|
||||
|
||||
}
|
||||
}
|
||||
try {
|
||||
return holder.value().updateShape(thisObj, args, superMethod);
|
||||
|
||||
@@ -147,7 +147,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerNMSPacketConsumer(PacketConsumers.SET_CREATIVE_SLOT, NetworkReflections.clazz$ServerboundSetCreativeModeSlotPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.LOGIN, NetworkReflections.clazz$ClientboundLoginPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESPAWN, NetworkReflections.clazz$ClientboundRespawnPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.INTERACT_ENTITY, NetworkReflections.clazz$ServerboundInteractPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, NetworkReflections.clazz$ClientboundEntityPositionSyncPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, NetworkReflections.clazz$ServerboundPickItemFromEntityPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, NetworkReflections.clazz$ServerboundRenameItemPacket);
|
||||
@@ -186,6 +185,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
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(PacketConsumers.INTERACT_ENTITY, this.packetIds.serverboundInteractPacket());
|
||||
}
|
||||
|
||||
public static BukkitNetworkManager instance() {
|
||||
|
||||
@@ -1103,13 +1103,13 @@ public class PacketConsumers {
|
||||
Object blockPos = FastNMS.INSTANCE.field$ServerboundPlayerActionPacket$pos(packet);
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
if (VersionHelper.isFolia()) {
|
||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
||||
platformPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
|
||||
try {
|
||||
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundPlayerActionPacket", e);
|
||||
}
|
||||
}, world, pos.x() >> 4, pos.z() >> 4);
|
||||
}, () -> {});
|
||||
} else {
|
||||
handlePlayerActionPacketOnMainThread(player, world, pos, packet);
|
||||
}
|
||||
@@ -1506,83 +1506,108 @@ public class PacketConsumers {
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> INTERACT_ENTITY = (user, event, packet) -> {
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> INTERACT_ENTITY = (user, event) -> {
|
||||
try {
|
||||
Player player = (Player) user.platformPlayer();
|
||||
if (player == null) return;
|
||||
int entityId;
|
||||
if (BukkitNetworkManager.hasModelEngine()) {
|
||||
int fakeId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
|
||||
entityId = CraftEngine.instance().compatibilityManager().interactionToBaseEntity(fakeId);
|
||||
} else {
|
||||
entityId = FastNMS.INSTANCE.field$ServerboundInteractPacket$entityId(packet);
|
||||
}
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int entityId = BukkitNetworkManager.hasModelEngine() ?
|
||||
CraftEngine.instance().compatibilityManager().interactionToBaseEntity(buf.readVarInt()) :
|
||||
buf.readVarInt();
|
||||
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
||||
if (furniture == null) return;
|
||||
Object action = NetworkReflections.handle$ServerboundInteractPacket$actionGetter.invokeExact(packet);
|
||||
Object actionType = NetworkReflections.method$ServerboundInteractPacket$Action$getType.invoke(action);
|
||||
if (actionType == null) return;
|
||||
Location location = furniture.baseEntity().getLocation();
|
||||
int actionType = buf.readVarInt();
|
||||
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
|
||||
if (serverPlayer.isSpectatorMode()) return;
|
||||
BukkitCraftEngine.instance().scheduler().sync().run(() -> {
|
||||
if (actionType == NetworkReflections.instance$ServerboundInteractPacket$ActionType$ATTACK) {
|
||||
Player platformPlayer = serverPlayer.platformPlayer();
|
||||
Location location = furniture.baseEntity().getLocation();
|
||||
|
||||
Runnable mainThreadTask;
|
||||
if (actionType == 1) {
|
||||
// ATTACK
|
||||
boolean usingSecondaryAction = buf.readBoolean();
|
||||
if (entityId != furniture.baseEntityId()) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(furniture.baseEntityId());
|
||||
buf.writeVarInt(actionType);
|
||||
buf.writeBoolean(usingSecondaryAction);
|
||||
}
|
||||
|
||||
mainThreadTask = () -> {
|
||||
// todo 冒险模式破坏工具白名单
|
||||
if (serverPlayer.isAdventureMode()) return;
|
||||
if (furniture.isValid()) {
|
||||
if (!BukkitCraftEngine.instance().antiGrief().canBreak(player, location)) {
|
||||
return;
|
||||
}
|
||||
FurnitureBreakEvent breakEvent = new FurnitureBreakEvent(serverPlayer.platformPlayer(), furniture);
|
||||
if (EventUtils.fireAndCheckCancel(breakEvent)) {
|
||||
return;
|
||||
}
|
||||
if (serverPlayer.isAdventureMode() ||
|
||||
!furniture.isValid() ||
|
||||
!BukkitCraftEngine.instance().antiGrief().canBreak(platformPlayer, location)
|
||||
) return;
|
||||
|
||||
// execute functions
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
||||
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
||||
);
|
||||
furniture.config().execute(context, EventTrigger.LEFT_CLICK);
|
||||
furniture.config().execute(context, EventTrigger.BREAK);
|
||||
FurnitureBreakEvent breakEvent = new FurnitureBreakEvent(serverPlayer.platformPlayer(), furniture);
|
||||
if (EventUtils.fireAndCheckCancel(breakEvent))
|
||||
return;
|
||||
|
||||
CraftEngineFurniture.remove(furniture, serverPlayer, !serverPlayer.isCreativeMode(), true);
|
||||
Cancellable cancellable = Cancellable.of(breakEvent::isCancelled, breakEvent::setCancelled);
|
||||
// execute functions
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.HAND, InteractionHand.MAIN_HAND)
|
||||
.withParameter(DirectContextParameters.ITEM_IN_HAND, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND))
|
||||
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
||||
);
|
||||
furniture.config().execute(context, EventTrigger.LEFT_CLICK);
|
||||
furniture.config().execute(context, EventTrigger.BREAK);
|
||||
if (cancellable.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
} else if (actionType == NetworkReflections.instance$ServerboundInteractPacket$ActionType$INTERACT_AT) {
|
||||
InteractionHand hand;
|
||||
Location interactionPoint;
|
||||
try {
|
||||
Object interactionHand = NetworkReflections.handle$ServerboundInteractPacket$InteractionAtLocationAction$handGetter.invokeExact(action);
|
||||
hand = interactionHand == CoreReflections.instance$InteractionHand$MAIN_HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
Object vec3 = NetworkReflections.handle$ServerboundInteractPacket$InteractionAtLocationAction$locationGetter.invokeExact(action);
|
||||
|
||||
double x = FastNMS.INSTANCE.field$Vec3$x(vec3);
|
||||
double y = FastNMS.INSTANCE.field$Vec3$y(vec3);
|
||||
double z = FastNMS.INSTANCE.field$Vec3$z(vec3);
|
||||
interactionPoint = new Location(location.getWorld(), x, y, z);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Failed to get interaction hand from interact packet", e);
|
||||
}
|
||||
CraftEngineFurniture.remove(furniture, serverPlayer, !serverPlayer.isCreativeMode(), true);
|
||||
};
|
||||
} else if (actionType == 2) {
|
||||
// INTERACT_AT
|
||||
float x = buf.readFloat();
|
||||
float y = buf.readFloat();
|
||||
float z = buf.readFloat();
|
||||
Location interactionPoint = new Location(platformPlayer.getWorld(), x, y, z);
|
||||
InteractionHand hand = buf.readVarInt() == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
boolean usingSecondaryAction = buf.readBoolean();
|
||||
if (entityId != furniture.baseEntityId()) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(furniture.baseEntityId());
|
||||
buf.writeVarInt(actionType);
|
||||
buf.writeFloat(x).writeFloat(y).writeFloat(z);
|
||||
buf.writeVarInt(hand == InteractionHand.MAIN_HAND ? 0 : 1);
|
||||
buf.writeBoolean(usingSecondaryAction);
|
||||
}
|
||||
|
||||
mainThreadTask = () -> {
|
||||
FurnitureInteractEvent interactEvent = new FurnitureInteractEvent(serverPlayer.platformPlayer(), furniture, hand, interactionPoint);
|
||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
Cancellable cancellable = Cancellable.of(interactEvent::isCancelled, interactEvent::setCancelled);
|
||||
// execute functions
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.FURNITURE, furniture)
|
||||
.withParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||
.withParameter(DirectContextParameters.HAND, hand)
|
||||
.withParameter(DirectContextParameters.POSITION, furniture.position())
|
||||
);
|
||||
furniture.config().execute(context, EventTrigger.RIGHT_CLICK);
|
||||
if (cancellable.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.isSneaking()) {
|
||||
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
||||
if (serverPlayer.isSecondaryUseActive() && itemInHand != null) {
|
||||
// try placing another furniture above it
|
||||
AABB hitBox = furniture.aabbByEntityId(entityId);
|
||||
if (hitBox == null) return;
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
if (itemInHand == null) return;
|
||||
Optional<CustomItem<ItemStack>> optionalCustomitem = itemInHand.getCustomItem();
|
||||
Location eyeLocation = player.getEyeLocation();
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||
Location eyeLocation = platformPlayer.getEyeLocation();
|
||||
Vector direction = eyeLocation.getDirection();
|
||||
Location endLocation = eyeLocation.clone();
|
||||
endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange()));
|
||||
@@ -1591,8 +1616,8 @@ public class PacketConsumers {
|
||||
return;
|
||||
}
|
||||
EntityHitResult hitResult = result.get();
|
||||
if (optionalCustomitem.isPresent() && !optionalCustomitem.get().behaviors().isEmpty()) {
|
||||
for (ItemBehavior behavior : optionalCustomitem.get().behaviors()) {
|
||||
if (optionalCustomItem.isPresent() && !optionalCustomItem.get().behaviors().isEmpty()) {
|
||||
for (ItemBehavior behavior : optionalCustomItem.get().behaviors()) {
|
||||
if (behavior instanceof FurnitureItemBehavior) {
|
||||
behavior.useOnBlock(new UseOnContext(serverPlayer, InteractionHand.MAIN_HAND, new BlockHitResult(hitResult.hitLocation(), hitResult.direction(), BlockPos.fromVec3d(hitResult.hitLocation()), false)));
|
||||
return;
|
||||
@@ -1601,7 +1626,12 @@ public class PacketConsumers {
|
||||
}
|
||||
// now simulate vanilla item behavior
|
||||
serverPlayer.setResendSound();
|
||||
FastNMS.INSTANCE.simulateInteraction(serverPlayer.serverPlayer(), DirectionUtils.toNMSDirection(hitResult.direction()), hitResult.hitLocation().x, hitResult.hitLocation().y, hitResult.hitLocation().z, LocationUtils.toBlockPos(hitResult.blockPos()));
|
||||
FastNMS.INSTANCE.simulateInteraction(
|
||||
serverPlayer.serverPlayer(),
|
||||
DirectionUtils.toNMSDirection(hitResult.direction()),
|
||||
hitResult.hitLocation().x, hitResult.hitLocation().y, hitResult.hitLocation().z,
|
||||
LocationUtils.toBlockPos(hitResult.blockPos())
|
||||
);
|
||||
} else {
|
||||
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
||||
if (furniture.tryOccupySeat(seatPos)) {
|
||||
@@ -1609,8 +1639,29 @@ public class PacketConsumers {
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
} else if (actionType == 0) {
|
||||
int hand = buf.readVarInt();
|
||||
boolean usingSecondaryAction = buf.readBoolean();
|
||||
if (entityId != furniture.baseEntityId()) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(furniture.baseEntityId());
|
||||
buf.writeVarInt(actionType);
|
||||
buf.writeVarInt(hand);
|
||||
buf.writeBoolean(usingSecondaryAction);
|
||||
}
|
||||
}, player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (VersionHelper.isFolia()) {
|
||||
platformPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> mainThreadTask.run(), () -> {});
|
||||
} else {
|
||||
BukkitCraftEngine.instance().scheduler().executeSync(mainThreadTask);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundInteractPacket", e);
|
||||
}
|
||||
|
||||
@@ -57,4 +57,6 @@ public interface PacketIds {
|
||||
int serverboundContainerClickPacket();
|
||||
|
||||
int serverboundSetCreativeModeSlotPacket();
|
||||
|
||||
int serverboundInteractPacket();
|
||||
}
|
||||
|
||||
@@ -144,4 +144,9 @@ public class PacketIds1_20 implements PacketIds {
|
||||
public int clientboundBlockEventPacket() {
|
||||
return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundBlockEventPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int serverboundInteractPacket() {
|
||||
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ServerboundInteractPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,4 +143,9 @@ public class PacketIds1_20_5 implements PacketIds {
|
||||
public int serverboundSetCreativeModeSlotPacket() {
|
||||
return PacketIdFinder.serverboundByName("minecraft:set_creative_mode_slot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int serverboundInteractPacket() {
|
||||
return PacketIdFinder.serverboundByName("minecraft:interact");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,6 +558,8 @@ public class BukkitServerPlayer extends Player {
|
||||
int currentTick = gameTicks();
|
||||
// optimize break speed, otherwise it would be too fast
|
||||
if (currentTick - this.lastSuccessfulBreak <= 5) return;
|
||||
Object destroyedState = this.destroyedState;
|
||||
if (destroyedState == null) return;
|
||||
try {
|
||||
org.bukkit.entity.Player player = platformPlayer();
|
||||
double range = getCachedInteractionRange();
|
||||
@@ -575,7 +577,7 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
// send hit sound if the sound is removed
|
||||
if (currentTick - this.lastHitBlockTime > 3) {
|
||||
Object blockOwner = FastNMS.INSTANCE.method$BlockState$getBlock(this.destroyedState);
|
||||
Object blockOwner = FastNMS.INSTANCE.method$BlockState$getBlock(destroyedState);
|
||||
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(blockOwner);
|
||||
Object soundEvent = CoreReflections.field$SoundType$hitSound.get(soundType);
|
||||
Object soundId = FastNMS.INSTANCE.field$SoundEvent$location(soundEvent);
|
||||
@@ -601,8 +603,8 @@ public class BukkitServerPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
float progressToAdd = getDestroyProgress(this.destroyedState, hitPos);
|
||||
int id = BlockStateUtils.blockStateToId(this.destroyedState);
|
||||
float progressToAdd = getDestroyProgress(destroyedState, hitPos);
|
||||
int id = BlockStateUtils.blockStateToId(destroyedState);
|
||||
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
// double check custom block
|
||||
if (customState != null && !customState.isEmpty()) {
|
||||
@@ -612,13 +614,13 @@ public class BukkitServerPlayer extends Player {
|
||||
// it's correct on plugin side
|
||||
if (blockSettings.isCorrectTool(item.id())) {
|
||||
// but not on serverside
|
||||
if (!FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), this.destroyedState)) {
|
||||
if (!FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), destroyedState)) {
|
||||
// we fix the speed
|
||||
progressToAdd = progressToAdd * (10f / 3f);
|
||||
}
|
||||
} else {
|
||||
// not a correct tool on plugin side and not a correct tool on serverside
|
||||
if (!blockSettings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), this.destroyedState)) {
|
||||
if (!blockSettings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(item.getLiteralObject(), destroyedState)) {
|
||||
progressToAdd = progressToAdd * (10f / 3f) * blockSettings.incorrectToolSpeed();
|
||||
}
|
||||
}
|
||||
@@ -681,7 +683,7 @@ public class BukkitServerPlayer extends Player {
|
||||
double d1 = (double) hitPos.y() - otherLocation.getY();
|
||||
double d2 = (double) hitPos.z() - otherLocation.getZ();
|
||||
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
|
||||
this.plugin.networkManager().sendPacket(this.plugin.adapt(other), packet);
|
||||
FastNMS.INSTANCE.sendPacket(FastNMS.INSTANCE.field$Player$connection$connection(FastNMS.INSTANCE.method$CraftPlayer$getHandle(other)), packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.type.Either;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
@@ -459,6 +460,14 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
}
|
||||
return new DynamicLoreModifier<>(dynamicLore);
|
||||
}, "dynamic-lore");
|
||||
registerDataFunction((obj) -> {
|
||||
if (obj instanceof Integer integer) {
|
||||
return new DyedColorModifier<>(integer);
|
||||
} else {
|
||||
Vector3f vector3f = MiscUtils.getAsVector3f(obj, "dyed-color");
|
||||
return new DyedColorModifier<>(MCUtils.fastFloor(vector3f.x) << 16 + MCUtils.fastFloor(vector3f.y) << 8 + MCUtils.fastFloor(vector3f.z));
|
||||
}
|
||||
}, "dyed-color");
|
||||
registerDataFunction((obj) -> {
|
||||
Map<String, Object> data = MiscUtils.castToMap(obj, false);
|
||||
return new TagsModifier<>(data);
|
||||
|
||||
@@ -36,6 +36,7 @@ public class ItemSettings {
|
||||
boolean dyeable = true;
|
||||
Helmet helmet = null;
|
||||
FoodData foodData = null;
|
||||
Key consumeReplacement = null;
|
||||
|
||||
private ItemSettings() {}
|
||||
|
||||
@@ -72,6 +73,7 @@ public class ItemSettings {
|
||||
newSettings.dyeable = settings.dyeable;
|
||||
newSettings.helmet = settings.helmet;
|
||||
newSettings.foodData = settings.foodData;
|
||||
newSettings.consumeReplacement = settings.consumeReplacement;
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
@@ -124,6 +126,11 @@ public class ItemSettings {
|
||||
return foodData;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Key consumeReplacement() {
|
||||
return consumeReplacement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Helmet helmet() {
|
||||
return helmet;
|
||||
@@ -139,6 +146,11 @@ public class ItemSettings {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemSettings consumeReplacement(Key key) {
|
||||
this.consumeReplacement = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemSettings canRepair(boolean canRepair) {
|
||||
this.canRepair = canRepair;
|
||||
return this;
|
||||
@@ -228,6 +240,7 @@ public class ItemSettings {
|
||||
int intValue = ResourceConfigUtils.getAsInt(value, "fuel-time");
|
||||
return settings -> settings.fuelTime(intValue);
|
||||
}));
|
||||
registerFactory("consume-replacement", (value -> settings -> settings.consumeReplacement(Key.of(value.toString()))));
|
||||
registerFactory("tags", (value -> {
|
||||
List<String> tags = MiscUtils.getAsStringList(value);
|
||||
return settings -> settings.tags(tags.stream().map(Key::of).collect(Collectors.toSet()));
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.momirealms.craftengine.core.item.modifier;
|
||||
|
||||
import net.momirealms.craftengine.core.item.ComponentKeys;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.NetworkItemHandler;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
|
||||
public class DyedColorModifier<I> implements ItemDataModifier<I> {
|
||||
private final int color;
|
||||
|
||||
public DyedColorModifier(int color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "dyed-color";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Item<I> item, ItemBuildContext context) {
|
||||
item.dyedColor(this.color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareNetworkItem(Item<I> item, ItemBuildContext context, CompoundTag networkData) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Tag previous = item.getNBTComponent(ComponentKeys.DYED_COLOR);
|
||||
if (previous != null) {
|
||||
networkData.put(ComponentKeys.DYED_COLOR.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous));
|
||||
} else {
|
||||
networkData.put(ComponentKeys.DYED_COLOR.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE));
|
||||
}
|
||||
} else {
|
||||
Tag previous = item.getNBTTag("display", "color");
|
||||
if (previous != null) {
|
||||
networkData.put("display.color", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous));
|
||||
} else {
|
||||
networkData.put("display.color", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=0.0.56.2
|
||||
project_version=0.0.56.3
|
||||
config_version=35
|
||||
lang_version=15
|
||||
project_group=net.momirealms
|
||||
@@ -51,7 +51,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.4
|
||||
anti_grief_version=0.17
|
||||
nms_helper_version=0.66.16
|
||||
nms_helper_version=0.66.17
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.31.23
|
||||
|
||||
Reference in New Issue
Block a user