9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-31 04:46:37 +00:00

重构entityview为实体处理器

This commit is contained in:
XiaoMoMi
2025-05-10 20:16:01 +08:00
parent d7f8f88106
commit 519c861139
15 changed files with 283 additions and 255 deletions

View File

@@ -4,6 +4,7 @@ import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitB
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler;
import net.momirealms.craftengine.bukkit.util.EntityUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.entity.furniture.*;
@@ -301,14 +302,14 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture));
furniture.initializeColliders();
for (Player player : display.getTrackedPlayers()) {
this.plugin.adapt(player).furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.fakeEntityIds());
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player));
}
}
} else {
LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture));
for (Player player : display.getTrackedPlayers()) {
this.plugin.adapt(player).furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.fakeEntityIds());
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player));
}
if (preventChange) {

View File

@@ -1,9 +1,7 @@
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;
@@ -12,22 +10,17 @@ 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.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.parser.standard.ByteParser;
import org.incendo.cloud.parser.standard.StringParser;
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;

View File

@@ -14,9 +14,7 @@ import net.momirealms.craftengine.bukkit.plugin.network.id.PacketIds1_20_5;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.plugin.CraftEngine;
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.*;
import net.momirealms.craftengine.core.util.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -152,7 +150,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);
registerNMSPacketConsumer(PacketConsumers.MOVE_AND_ROTATE_ENTITY, 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());
@@ -549,7 +547,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
FriendlyByteBuf buf = new FriendlyByteBuf(buffer);
int preProcessIndex = buf.readerIndex();
int packetId = buf.readVarInt();
ByteBufPacketEvent event = new ByteBufPacketEvent(packetId, buf);
int preIndex = buf.readerIndex();
ByteBufPacketEvent event = new ByteBufPacketEvent(packetId, buf, preIndex);
BukkitNetworkManager.this.handleByteBufPacket(this.player, event);
if (event.isCancelled()) {
buf.clear();

View File

@@ -1,59 +0,0 @@
package net.momirealms.craftengine.bukkit.plugin.network;
import net.momirealms.craftengine.core.util.Cancellable;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class ByteBufPacketEvent implements Cancellable {
private boolean cancelled;
private List<Runnable> delayedTasks = null;
private final FriendlyByteBuf buf;
private boolean changed;
private final int packetID;
public ByteBufPacketEvent(int packetID, FriendlyByteBuf buf) {
this.buf = buf;
this.packetID = packetID;
}
public int packetID() {
return packetID;
}
public FriendlyByteBuf getBuffer() {
return buf;
}
public void setChanged(boolean dirty) {
this.changed = dirty;
}
public boolean changed() {
return changed;
}
public void addDelayedTask(Runnable task) {
if (delayedTasks == null) {
delayedTasks = new ArrayList<>();
}
delayedTasks.add(task);
}
public List<Runnable> getDelayedTasks() {
return Optional.ofNullable(delayedTasks).orElse(Collections.emptyList());
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,57 +0,0 @@
package net.momirealms.craftengine.bukkit.plugin.network;
import net.momirealms.craftengine.core.util.Cancellable;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class NMSPacketEvent implements Cancellable {
private final Object packet;
private boolean cancelled;
private List<Runnable> delayedTasks = null;
private Object newPacket = null;
public NMSPacketEvent(Object packet) {
this.packet = packet;
}
public Object getPacket() {
return packet;
}
public void replacePacket(@NotNull Object newPacket) {
this.newPacket = newPacket;
}
public boolean isUsingNewPacket() {
return newPacket != null;
}
public Object optionalNewPacket() {
return newPacket;
}
public void addDelayedTask(Runnable task) {
if (delayedTasks == null) {
delayedTasks = new ArrayList<>();
}
delayedTasks.add(task);
}
public List<Runnable> getDelayedTasks() {
return Optional.ofNullable(delayedTasks).orElse(Collections.emptyList());
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -17,6 +17,10 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.pack.BukkitPackManager;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
import net.momirealms.craftengine.bukkit.plugin.network.handler.ArmorStandPacketHandler;
import net.momirealms.craftengine.bukkit.plugin.network.handler.BlockDisplayPacketHandler;
import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler;
import net.momirealms.craftengine.bukkit.plugin.network.handler.TextDisplayPacketHandler;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.*;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
@@ -31,11 +35,7 @@ import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
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.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.plugin.network.*;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.BlockHitResult;
import net.momirealms.craftengine.core.world.BlockPos;
@@ -421,7 +421,8 @@ public class PacketConsumers {
return;
}
EnumSet<? extends Enum<?>> enums = FastNMS.INSTANCE.field$ClientboundPlayerInfoUpdatePacket$actions(packet);
outer: {
outer:
{
for (Object entry : enums) {
if (entry == Reflections.instance$ClientboundPlayerInfoUpdatePacket$Action$UPDATE_DISPLAY_NAME) {
break outer;
@@ -1578,9 +1579,11 @@ public class PacketConsumers {
buf.writeShort(za);
}
} else if (type == Reflections.instance$EntityType$BLOCK_DISPLAY$registryId) {
user.entityView().put(id, Reflections.instance$EntityType$BLOCK_DISPLAY);
user.entityPacketHandlers().put(id, BlockDisplayPacketHandler.INSTANCE);
} else if (type == Reflections.instance$EntityType$TEXT_DISPLAY$registryId) {
user.entityView().put(id, Reflections.instance$EntityType$TEXT_DISPLAY);
user.entityPacketHandlers().put(id, TextDisplayPacketHandler.INSTANCE);
} else if (type == Reflections.instance$EntityType$ARMOR_STAND$registryId) {
user.entityPacketHandlers().put(id, ArmorStandPacketHandler.INSTANCE);
}
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e);
@@ -1595,7 +1598,7 @@ public class PacketConsumers {
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
if (furniture != null) {
user.furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.fakeEntityIds());
user.entityPacketHandlers().computeIfAbsent(entityId, k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
user.sendPacket(furniture.spawnPacket((Player) user.platformPlayer()), false);
if (Config.hideBaseEntity() && !furniture.hasExternalModel()) {
event.setCancelled(true);
@@ -1608,8 +1611,6 @@ 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);
@@ -1620,10 +1621,6 @@ public class PacketConsumers {
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);
}
@@ -1650,17 +1647,9 @@ public class PacketConsumers {
IntList intList = buf.readIntIdList();
for (int i = 0, size = intList.size(); i < size; i++) {
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) {
EntityPacketHandler handler = user.entityPacketHandlers().remove(entityId);
if (handler != null && handler.handleEntitiesRemove(intList)) {
isChange = true;
intList.add(subEntityId);
}
}
if (isChange) {
@@ -2012,131 +2001,11 @@ 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;
EntityPacketHandler handler = user.entityPacketHandlers().get(id);
if (handler != null) {
handler.handleSetEntityData(user, event);
}
Object entityType = user.entityView().get(id);
if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) {
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == EntityDataUtils.BLOCK_STATE_DATA_ID) {
Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
int stateId = BlockStateUtils.blockStateToId(blockState);
int newStateId;
if (!user.clientModEnabled()) {
newStateId = remap(stateId);
} else {
newStateId = remapMOD(stateId);
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId)
));
isChanged = true;
} else if (Config.interceptEntityName() && entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (optionalTextComponent.isPresent()) {
Object textComponent = optionalTextComponent.get();
String json = ComponentUtils.minecraftToJson(textComponent);
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
if (!tokens.isEmpty()) {
Component component = AdventureHelper.jsonToComponent(json);
for (Map.Entry<String, Component> token : tokens.entrySet()) {
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
));
isChanged = true;
}
}
}
}
if (isChanged) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
}
} else if (entityType == Reflections.instance$EntityType$TEXT_DISPLAY) {
if (Config.interceptTextDisplay()) {
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == EntityDataUtils.TEXT_DATA_ID) {
Object textComponent = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (textComponent == Reflections.instance$Component$empty) break;
String json = ComponentUtils.minecraftToJson(textComponent);
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
if (!tokens.isEmpty()) {
Component component = AdventureHelper.jsonToComponent(json);
for (Map.Entry<String, Component> token : tokens.entrySet()) {
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, ComponentUtils.adventureToMinecraft(component)));
isChanged = true;
break;
}
}
}
if (isChanged) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
}
}
} else if (entityType == Reflections.instance$EntityType$ARMOR_STAND) {
if (Config.interceptArmorStand()) {
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (optionalTextComponent.isPresent()) {
Object textComponent = optionalTextComponent.get();
String json = ComponentUtils.minecraftToJson(textComponent);
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
if (!tokens.isEmpty()) {
Component component = AdventureHelper.jsonToComponent(json);
for (Map.Entry<String, Component> token : tokens.entrySet()) {
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))));
isChanged = true;
break;
}
}
}
}
if (isChanged) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
}
}
} else if (Config.interceptEntityName()) {
if (Config.interceptEntityName()) {
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
@@ -2187,7 +2056,8 @@ public class PacketConsumers {
if (hasDisplay) {
displayName = buf.readNbt(false);
}
outside : if (displayName != null) {
outside:
if (displayName != null) {
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(displayName.getAsString());
if (tokens.isEmpty()) break outside;
Component component = AdventureHelper.tagToComponent(displayName);
@@ -2341,12 +2211,10 @@ public class PacketConsumers {
}
};
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_ENTITY_ALL = (user, event, packet) -> {
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_AND_ROTATE_ENTITY = (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

@@ -0,0 +1,62 @@
package net.momirealms.craftengine.bukkit.plugin.network.handler;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class ArmorStandPacketHandler implements EntityPacketHandler {
public static final ArmorStandPacketHandler INSTANCE = new ArmorStandPacketHandler();
@Override
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
if (!Config.interceptArmorStand()) {
return;
}
FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt();
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
@SuppressWarnings("unchecked")
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (optionalTextComponent.isPresent()) {
Object textComponent = optionalTextComponent.get();
String json = ComponentUtils.minecraftToJson(textComponent);
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
if (!tokens.isEmpty()) {
Component component = AdventureHelper.jsonToComponent(json);
for (Map.Entry<String, Component> token : tokens.entrySet()) {
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))));
isChanged = true;
break;
}
}
}
}
if (isChanged) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
}
}
}

View File

@@ -0,0 +1,76 @@
package net.momirealms.craftengine.bukkit.plugin.network.handler;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class BlockDisplayPacketHandler implements EntityPacketHandler {
public static final BlockDisplayPacketHandler INSTANCE = new BlockDisplayPacketHandler();
@Override
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt();
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == EntityDataUtils.BLOCK_STATE_DATA_ID) {
Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
int stateId = BlockStateUtils.blockStateToId(blockState);
int newStateId;
if (!user.clientModEnabled()) {
newStateId = PacketConsumers.remap(stateId);
} else {
newStateId = PacketConsumers.remapMOD(stateId);
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId)
));
isChanged = true;
} else if (Config.interceptEntityName() && entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
@SuppressWarnings("unchecked")
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (optionalTextComponent.isPresent()) {
Object textComponent = optionalTextComponent.get();
String json = ComponentUtils.minecraftToJson(textComponent);
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
if (!tokens.isEmpty()) {
Component component = AdventureHelper.jsonToComponent(json);
for (Map.Entry<String, Component> token : tokens.entrySet()) {
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
));
isChanged = true;
}
}
}
}
if (isChanged) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
}
}
}

View File

@@ -1,16 +1,15 @@
package net.momirealms.craftengine.bukkit.util;
package net.momirealms.craftengine.bukkit.plugin.network.handler;
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.bukkit.util.Reflections;
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.NMSPacketEvent;
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;
@@ -25,9 +24,10 @@ 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 final class CustomTridentPacketHandler {
private CustomTridentPacketHandler() {}
public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) {
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
@@ -40,19 +40,10 @@ public class CustomTridentUtils {
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);
}
}
@@ -150,14 +141,6 @@ public class CustomTridentUtils {
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

@@ -0,0 +1,20 @@
package net.momirealms.craftengine.bukkit.plugin.network.handler;
import it.unimi.dsi.fastutil.ints.IntList;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import java.util.List;
public class FurniturePacketHandler implements EntityPacketHandler {
private final List<Integer> fakeEntities;
public FurniturePacketHandler(List<Integer> fakeEntities) {
this.fakeEntities = fakeEntities;
}
@Override
public boolean handleEntitiesRemove(IntList entityIds) {
entityIds.addAll(this.fakeEntities);
return true;
}
}

View File

@@ -0,0 +1,59 @@
package net.momirealms.craftengine.bukkit.plugin.network.handler;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import java.util.List;
import java.util.Map;
public class TextDisplayPacketHandler implements EntityPacketHandler {
public static final TextDisplayPacketHandler INSTANCE = new TextDisplayPacketHandler();
@Override
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
if (!Config.interceptTextDisplay()) {
return;
}
FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt();
boolean isChanged = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == EntityDataUtils.TEXT_DATA_ID) {
Object textComponent = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (textComponent == Reflections.instance$Component$empty) break;
String json = ComponentUtils.minecraftToJson(textComponent);
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
if (!tokens.isEmpty()) {
Component component = AdventureHelper.jsonToComponent(json);
for (Map.Entry<String, Component> token : tokens.entrySet()) {
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
}
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, ComponentUtils.adventureToMinecraft(component)));
isChanged = true;
break;
}
}
}
if (isChanged) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeVarInt(id);
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
}
}
}

View File

@@ -19,8 +19,8 @@ import net.momirealms.craftengine.core.item.Item;
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.EntityPacketHandler;
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;
@@ -91,11 +91,8 @@ public class BukkitServerPlayer extends Player {
// cache interaction range here
private int lastUpdateInteractionRangeTick;
private double cachedInteractionRange;
// 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<>();
private final Map<Integer, EntityPacketHandler> entityTypeView = new ConcurrentHashMap<>();
public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) {
this.channel = channel;
@@ -107,13 +104,6 @@ public class BukkitServerPlayer extends Player {
this.serverPlayerRef = new WeakReference<>(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player));
this.uuid = player.getUniqueId();
this.name = player.getName();
// if (Reflections.method$CraftPlayer$setSimplifyContainerDesyncCheck != null) {
// try {
// Reflections.method$CraftPlayer$setSimplifyContainerDesyncCheck.invoke(player, true);
// } catch (Exception e) {
// this.plugin.logger().warn("Failed to setSimplifyContainerDesyncCheck", e);
// }
// }
}
@Override
@@ -731,25 +721,10 @@ public class BukkitServerPlayer extends Player {
}
@Override
public Map<Integer, List<Integer>> furnitureView() {
return this.furnitureView;
}
@Override
public Map<Integer, Object> entityView() {
public Map<Integer, EntityPacketHandler> entityPacketHandlers() {
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();
}
@@ -812,7 +787,6 @@ public class BukkitServerPlayer extends Player {
@Override
public void clearView() {
this.entityTypeView.clear();
this.furnitureView.clear();
}
@Override

View File

@@ -6408,6 +6408,7 @@ public class Reflections {
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;
public static final int instance$EntityType$ARMOR_STAND$registryId;
static {
try {
@@ -6416,6 +6417,7 @@ public class Reflections {
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);
instance$EntityType$ARMOR_STAND$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$ARMOR_STAND);
} catch (Exception e) {
throw new RuntimeException(e);
}