package org.itxtech.synapseapi.utils; import cn.nukkit.entity.Entity; import cn.nukkit.entity.data.EntityData; import cn.nukkit.entity.data.EntityMetadata; import cn.nukkit.entity.data.LongEntityData; import cn.nukkit.network.protocol.*; import cn.nukkit.utils.MainLogger; import com.google.common.collect.Sets; import java.util.Arrays; import java.util.Set; /** * DataPacketEidReplacer * =============== * author: boybook * EaseCation Network Project * codefuncore * =============== */ public class DataPacketEidReplacer { private static final Set<Integer> replaceMetadata = Sets.newHashSet(Entity.DATA_OWNER_EID, Entity.DATA_LEAD_HOLDER_EID, Entity.DATA_TRADING_PLAYER_EID, Entity.DATA_TARGET_EID); public static DataPacket replace(DataPacket pk, long from, long to) { DataPacket packet = pk.clone(); boolean change = false; //TODO: return original packet if there is no change switch (packet.pid()) { case AddPlayerPacket.NETWORK_ID: AddPlayerPacket app = (AddPlayerPacket) packet; EntityMetadata replaced = replaceMetadata(app.metadata, from, to); if (replaced != null) { change = true; app.metadata = replaced; } break; case AddEntityPacket.NETWORK_ID: AddEntityPacket aep = (AddEntityPacket) packet; replaced = replaceMetadata(aep.metadata, from, to); if (replaced != null) { change = true; aep.metadata = replaced; } break; case AddItemEntityPacket.NETWORK_ID: AddItemEntityPacket aiep = (AddItemEntityPacket) packet; replaced = replaceMetadata(aiep.metadata, from, to); if (replaced != null) { change = true; aiep.metadata = replaced; } break; case AnimatePacket.NETWORK_ID: if (((AnimatePacket) packet).eid == from) { ((AnimatePacket) packet).eid = to; change = true; } break; case TakeItemEntityPacket.NETWORK_ID: if (((TakeItemEntityPacket) packet).entityId == from) { ((TakeItemEntityPacket) packet).entityId = to; change = true; } break; case SetEntityMotionPacket.NETWORK_ID: if (((SetEntityMotionPacket) packet).eid == from) { ((SetEntityMotionPacket) packet).eid = to; change = true; } break; case SetEntityLinkPacket.NETWORK_ID: SetEntityLinkPacket selp = (SetEntityLinkPacket) packet; if (selp.riderUniqueId == from) { selp.riderUniqueId = to; change = true; } if (selp.vehicleUniqueId == from) { selp.vehicleUniqueId = to; change = true; } break; case SetEntityDataPacket.NETWORK_ID: SetEntityDataPacket sedp = (SetEntityDataPacket) packet; if (sedp.eid == from) { sedp.eid = to; change = true; } replaced = replaceMetadata(sedp.metadata, from, to); if (replaced != null) { change = true; sedp.metadata = replaced; } break; case UpdateAttributesPacket.NETWORK_ID: if (((UpdateAttributesPacket) packet).entityId == from) { ((UpdateAttributesPacket) packet).entityId = to; change = true; } break; case EntityEventPacket.NETWORK_ID: if (((EntityEventPacket) packet).eid == from) { ((EntityEventPacket) packet).eid = to; change = true; } break; case MovePlayerPacket.NETWORK_ID: if (((MovePlayerPacket) packet).eid == from) { ((MovePlayerPacket) packet).eid = to; change = true; } break; case MobEquipmentPacket.NETWORK_ID: if (((MobEquipmentPacket) packet).eid == from) { ((MobEquipmentPacket) packet).eid = to; change = true; } break; case MobEffectPacket.NETWORK_ID: if (((MobEffectPacket) packet).eid == from) { ((MobEffectPacket) packet).eid = to; change = true; } break; case MoveEntityAbsolutePacket.NETWORK_ID: if (((MoveEntityAbsolutePacket) packet).eid == from) { ((MoveEntityAbsolutePacket) packet).eid = to; change = true; } break; case MobArmorEquipmentPacket.NETWORK_ID: if (((MobArmorEquipmentPacket) packet).eid == from) { ((MobArmorEquipmentPacket) packet).eid = to; change = true; } break; case PlayerListPacket.NETWORK_ID: Arrays.stream(((PlayerListPacket) packet).entries).filter(entry -> entry.entityId == from).forEach(entry -> entry.entityId = to); change = true; break; case BossEventPacket.NETWORK_ID: if (((BossEventPacket) packet).bossEid == from) { ((BossEventPacket) packet).bossEid = to; change = true; } break; case AdventureSettingsPacket.NETWORK_ID: if (((AdventureSettingsPacket) packet).entityUniqueId == from) { ((AdventureSettingsPacket) packet).entityUniqueId = to; change = true; } break; case ProtocolInfo.UPDATE_EQUIPMENT_PACKET: if (((UpdateEquipmentPacket) packet).eid == from) { ((UpdateEquipmentPacket) packet).eid = to; change = true; } break; } if (change) { packet.isEncoded = false; return packet; } return pk; } private static EntityMetadata replaceMetadata(EntityMetadata data, long from, long to) { boolean changed = false; for (Integer key : replaceMetadata) { try { EntityData ed = data.get(key); if (ed == null) { continue; } if (ed.getType() != Entity.DATA_TYPE_LONG) { MainLogger.getLogger().info("Wrong entity data type (" + key + ") expected 'Long' got '" + dataTypeToString(ed.getType()) + "'"); continue; } long value = ((LongEntityData) ed).getData(); if (value == from) { if (!changed) { data = cloneMetadata(data); changed = true; } data.putLong(key, to); } } catch (Exception e) { MainLogger.getLogger().error("Exception while replacing metadata '" + key + "'", e); } } if (!changed) return null; return data; } private static EntityMetadata cloneMetadata(EntityMetadata data) { EntityMetadata newData = new EntityMetadata(); for (EntityData value : data.getMap().values()) { newData.put(value); } return newData; } private static String dataTypeToString(int type) { switch (type) { case Entity.DATA_TYPE_BYTE: return "Byte"; case Entity.DATA_TYPE_SHORT: return "Short"; case Entity.DATA_TYPE_INT: return "Int"; case Entity.DATA_TYPE_FLOAT: return "Float"; case Entity.DATA_TYPE_STRING: return "String"; case Entity.DATA_TYPE_NBT: return "Slot"; case Entity.DATA_TYPE_POS: return "Pos"; case Entity.DATA_TYPE_LONG: return "Long"; case Entity.DATA_TYPE_VECTOR3F: return "Vector3f"; } return "Unknown"; } }