struct sConfig { struct sPlayerESP { bool Alert; bool Line; bool Box; bool Skeleton; bool NoBot; bool LootBox; bool 血量; bool 剩余人数; bool 名字; bool 距离; float RadarX; float RadarY; bool Radar; bool RadarDraw2; bool Radar1; bool Radar2; bool Radar3; bool Radar4; }; sPlayerESP PlayerESP{0}; struct sOTHER { bool HIDEESP; }; sOTHER OTHER{0}; }; sConfig Config{0}; bool 提示=true; bool 物资功能=false; bool 单机设置=true; bool 联机调试=false; bool 功能设置=false; bool 物资调试=false; bool 坐标调试=false; bool HIDEESP = true; bool 人数 = false; bool 世界 = false; bool 更多功能 = false; bool 高跳 = false; float 高度 = 500.0f; bool chongchongche = false; float chongchongche1; float chongchongche2; float tocdoquay = 0.0f; bool 人物变大 = false; float 巨人 = 1.0f; bool 飞天跳开 = false; bool 飞天跳关 = false; bool 飞天2 = false; bool 飞天1 = false; bool 飞天关 = false; bool 能量加速开 = false; bool 能量加速关 = false; bool 伤害测试2 = false; bool 枪械一套 = false; bool 枪械变大 = false; float Gun_Size = 1.0f; bool 开启伤害 = false; float 伤害值 = 0.0f; float 伤害倍率 = 1.0f; bool 广角 = false; float 视角 = 90.0f; bool 自控初始化 = false; bool 喇叭飞天 = false; bool 载具加速 = false; bool 转圈 = false; bool 转圈2 = false; bool 无视碰撞开 = false; bool 无视重力开 = false; bool 老爷模式 = false; bool 飞船模式 = false; float 载具速度 = 1.0f; float 喇叭高度 = 1.0f; float XXXC = 3.0f; bool 开发者菜单 = false; bool 修复着陆 = false; bool 修复部分 = false; bool 修复车辆 = false; bool DamageFix = false; float 驾驶员X偏移 = 100.0f; float 驾驶员Y偏移 = 0.0f; float 驾驶员Z偏移 = 80.0f; float 乘客X偏移 = 50.0f; float 乘客Y偏移 = 50.0f; float 乘客Z偏移 = 80.0f; extern void 执行单次生成(); extern void 更新建筑跟随状态(); extern void 探测并添加附近建筑(float Radius); extern void 清空建筑列表(); extern void 加载选中的建筑(); extern void 获取对象(); inline bool 建筑跟随模式 = false; inline float 建筑探测半径 = 1000.0f; inline float 建筑生成偏移 = 500.0f; inline char 建筑路径输入[256] = {0}; bool(*ogm)(); bool gm(){ return true; } void CreateItem(int ItemType, int TypeSpecificID, int Count) { 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=ItemType; Item.TypeSpecificID=TypeSpecificID; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(Count); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void src(int ItemType, int TypeSpecificID, int Count) { 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=ItemType; Item.TypeSpecificID=TypeSpecificID; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(Count); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } // 武器皮肤 - 类型1 (正确) void AKM_Chicheng() { src(1, 101001001, 10); } void AKM_Rongyao() { src(1, 101001002, 10); } void AKM_Wumujinwen() { src(1, 101001003, 10); } void AKM_Xueshi() { src(1, 101001004, 10); } void AKM_Kuangnu() { src(1, 101001005, 10); } void M16A4_Shachi() { src(1, 101002001, 10); } void M16A4_Qingyao() { src(1, 101002002, 10); } void M16A4_Wumujinwen() { src(1, 101002003, 10); } void M16A4_Huangshi() { src(1, 101002004, 10); } void M16A4_Yezhanyinghao() { src(1, 101002005, 10); } void M16A4_Kuangnu() { src(1, 101002006, 10); } void SCARL_Kuangnu() { src(1, 101003001, 10); } void SCARL_Wumujinwen() { src(1, 101003002, 10); } void SCARL_Chicheng() { src(1, 101003003, 10); } void SCARL_Xueshi() { src(1, 101003004, 10); } void M416_RocketGirl() { src(1, 101004001, 10); } void M416_Wumujinwen() { src(1, 101004002, 10); } void M416_Kuishe() { src(1, 101004003, 10); } void M416_Tuya() { src(1, 101004004, 10); } void M416_Shamofengbao() { src(1, 101004005, 10); } void M416_Xueyumicai() { src(1, 101004006, 10); } void M416_Xueshi() { src(1, 101004007, 10); } void M416_Chicheng() { src(1, 101004008, 10); } void M416_Spring() { src(1, 101004009, 10); } void GROZA_Kuangnu() { src(1, 101005001, 10); } void AUG_Xueshi() { src(1, 101006001, 10); } void UZI_Kuangnu() { src(1, 102001001, 10); } void UMP9_Chicheng() { src(1, 102002001, 10); } void UMP9_Rongyao() { src(1, 102002002, 10); } void UMP9_RocketGirl() { src(1, 102002003, 10); } void UMP9_Spring() { src(1, 102002004, 10); } void Kar98K_Qingyao() { src(1, 103001001, 10); } void Kar98K_Wumujinwen() { src(1, 103001002, 10); } void Kar98K_FireLava() { src(1, 103001003, 10); } void Kar98K_Xueshi() { src(1, 103001004, 10); } void Kar98K_Spring() { src(1, 103001005, 10); } void AWM_Rainbow() { src(1, 103003001, 10); } void SKS_Chicheng() { src(1, 103004001, 10); } void S686_Chicheng() { src(1, 104001001, 10); } void P92_Kuangnu() { src(1, 106001001, 10); } void P1911_Qingyao() { src(1, 106002001, 10); } void Crowbar_RedNight() { src(1, 108002001, 10); } void Pan_DoubleYolk() { src(1, 108004001, 10); } void Pan_Survivor() { src(1, 108004002, 10); } void Pan_NoHunt() { src(1, 108004003, 10); } void Pan_RottenTomato() { src(1, 108004004, 10); } void Pan_Forward() { src(1, 108004005, 10); } void Pan_RedNight() { src(1, 108004006, 10); } // 表情动作 - 类型22 (正确) void 你好() { src(22, 2200101, 20); } void 感谢() { src(22, 2200201, 20); } void 鼓掌() { src(22, 2200301, 20); } void 大笑() { src(22, 2200401, 20); } void 来这里() { src(22, 2200501, 20); } void 走() { src(22, 2200601, 20); } void 否定() { src(22, 2200701, 20); } void 肯定() { src(22, 2200801, 20); } void 投降() { src(22, 2200901, 20); } void 愤怒() { src(22, 2201001, 20); } void 摇摆舞() { src(22, 2201101, 20); } void 电摇() { src(22, 2201201, 20); } void 拍灰舞() { src(22, 2201301, 20); } void 俄舞() { src(22, 2201401, 20); } void 安静() { src(22, 2201501, 20); } void 雀跃() { src(22, 2201601, 20); } void 崩溃() { src(22, 2201701, 20); } void 海带舞() { src(22, 2201801, 20); } void 街舞() { src(22, 2201901, 20); } void 壁虎步() { src(22, 2202001, 20); } void 机械舞() { src(22, 2202101, 20); } void 蹦迪舞() { src(22, 2202201, 20); } void 斗舞() { src(22, 2202301, 20); } void 秀舞() { src(22, 2202401, 20); } void 拉票舞() { src(22, 2202501, 20); } void 创造舞() { src(22, 2202601, 20); } void 三连赞() { src(22, 2202701, 20); } void 桑巴舞() { src(22, 2202801, 20); } void 空翻() { src(22, 2202901, 20); } void 摇篮舞() { src(22, 2203001, 20); } void 摆裙舞() { src(22, 2203101, 20); } void 吃鸡舞() { src(22, 2203201, 20); } void 抖胸舞() { src(22, 2203301, 20); } void 青蛙舞() { src(22, 2203401, 20); } void 甩手舞() { src(22, 2203501, 20); } void 点赞() { src(22, 2203601, 20); } void 欢庆舞() { src(22, 2203701, 20); } void 螃蟹舞() { src(22, 2203801, 20); } void 快看我() { src(22, 2203901, 20); } void 难过() { src(22, 2204001, 20); } void 扭秧歌() { src(22, 2204101, 20); } void 拜年男() { src(22, 2204201, 20); } void 红包来了() { src(22, 2204301, 20); } void 拜年女() { src(22, 2204401, 20); } // 服装 - 类型4 (正确) void 雪地吉利服() { src(4, 403038, 10); } void 晶翼女神套装() { src(4, 403409, 10); } void 黑曜金尊套装() { src(4, 403410, 10); } void 火箭少女101() { src(4, 453021, 10); } void 至尊金龙外套() { src(4, 403188, 10); } void S1战斗裤() { src(4, 404049, 10); } void S1战斗外套() { src(4, 403124, 10); } void 小黄衣() { src(4, 403017, 10); } void 小黄裤() { src(4, 404001, 10); } void 黑色连帽大衣() { src(4, 403184, 10); } void 西部牛仔面罩() { src(4, 402037, 10); } void 黑色rock() { src(4, 403178, 10); } void 青色面罩() { src(4, 402032, 10); } void 师傅专用外套() { src(4, 403075, 10); } void 时尚圣诞套装() { src(4, 403393, 10); } void 卡路里套装() { src(4, 403408, 10); } // 货币 - 类型100 (正确) void 现金() { src(100, 1011, 520); } void Q币() { src(100, 1012, 520); } void 点券() { src(100, 1006, 520); } // 特效道具 - 类型30 (正确) void 新年烟花() { src(30, 3000301, 50); } void 新年爆竹() { src(30, 3000302, 50); } void 红包() { src(30, 3001027, 50); } void 坚甲() { src(30, 3001028, 50); } void 利爪() { src(30, 3001029, 50); } void 小鸡() { src(30, 3002001, 50); } void 鸡蛋() { src(30, 3002002, 50); } void 南瓜() { src(30, 3001013, 50); } void 圣诞糖果() { src(30, 3001014, 50); } void 西瓜() { src(30, 3001001, 50); } void 小黄鸭() { src(30, 3001002, 90); } void 鸡() { src(30, 3001003, 90); } // 道具/材料 - 类型16 (正确) void 机密情报() { src(16, 1602056, 50); } void 鸡神奖杯() { src(16, 1602046, 50); } void 胜利手雷() { src(16, 1602039, 50); } void 足球() { src(16, 1602030, 50); } // 消耗品 - 类型6 (正确,但需要修正参数个数) void 震爆弹() { src(6, 602001, 50); } void 烟雾弹() { src(6, 602002, 50); } void 燃烧瓶() { src(6, 602003, 50); } void 破片手榴弹() { src(6, 602004, 50); } void 跳舞弹() { src(6, 602006, 50); } // 修正参数个数错误: void 大春雷() { src(6, 602010, 50); } // 原来有4个参数 void 鞭炮() { src(6, 602011, 50); } // 原来有4个参数 void 小春雷() { src(6, 602012, 50); } // 原来有4个参数 void 南瓜炸弹() { src(6, 602013, 50); } // 原来有4个参数 void 苹果() { src(6, 602005, 50); } void 圣诞玩具苹果() { src(6, 602007, 50); } void 圣诞小鸡玩偶() { src(6, 602008, 50); } void 冬季雪球() { src(6, 602009, 50); } void 肾上腺素() { src(6, 601002, 50); } // 武器 - 类型1 (正确) void AKM() { src(1, 101001, 10); } void M416() { src(1, 101004, 10); } void AWM() { src(1, 103003, 10); } void M16A4() { src(1, 101002, 10); } void GROZA() { src(1, 101005, 10); } void SCARL() { src(1, 101003, 10); } void AUG() { src(1, 101006, 10); } void QBZ() { src(1, 101007, 10); } void M762() { src(1, 101008, 10); } void MK47() { src(1, 101009, 10); } void G36C() { src(1, 101010, 10); } void UZI() { src(1, 102001, 10); } void UMP9() { src(1, 102002, 10); } void Vector() { src(1, 102003, 10); } void Thompson() { src(1, 102004, 10); } void PP19() { src(1, 102005, 10); } void Kar98K() { src(1, 103001, 10); } void M24() { src(1, 103002, 10); } void SKS() { src(1, 103004, 10); } void VSS() { src(1, 103005, 10); } void Mini14() { src(1, 103006, 10); } void Mk14() { src(1, 103007, 10); } void Win94() { src(1, 103008, 10); } void SLR() { src(1, 103009, 10); } void QBU() { src(1, 103010, 10); } void S686() { src(1, 104001, 10); } void S1897() { src(1, 104002, 10); } void S12K() { src(1, 104003, 10); } void M249() { src(1, 105001, 10); } void DP28() { src(1, 105002, 10); } void P92() { src(1, 106001, 10); } void P1911() { src(1, 106002, 10); } void R1895() { src(1, 106003, 10); } void P18C() { src(1, 106004, 10); } void R45() { src(1, 106005, 10); } void SawedOff() { src(1, 106006, 10); } void SignalGun() { src(1, 106007, 10); } void Scorpion() { src(1, 106008, 10); } void ChickenFirework() { src(1, 106095, 10); } void LanternFirework() { src(1, 106096, 10); } void BeastSignal() { src(1, 106097, 10); } void ChristmasSignal() { src(1, 106098, 10); } void NewYearFirework() { src(1, 106099, 10); } void Crossbow() { src(1, 107001, 10); } void RiotShield() { src(1, 107003, 10); } void Machete() { src(1, 108001, 10); } void Crowbar() { src(1, 108002, 10); } void Sickle() { src(1, 108003, 10); } void Pan() { src(1, 108004, 10); } // 弹药 - 类型3 (正确) void Bullet762() { src(3, 302001, 900); } void Bullet556() { src(3, 303001, 900); } void ShotgunShell() { src(3, 304001, 900); } void Bullet45() { src(3, 305001, 900); } void Magnum() { src(3, 306001, 900); } void SignalFlare() { src(3, 308001, 900); } void Arrow() { src(3, 307001, 900); } void FireworkShell() { src(3, 308002, 900); } void BeastBait() { src(3, 308003, 900); } // 配件 - 类型2 (修正:之前是类型1,应该改为类型2) void Choke() { src(2, 201001, 10); } void SMGCompensator() { src(2, 201002, 10); } void SniperCompensator() { src(2, 201003, 10); } void SMGFlashHider() { src(2, 201004, 10); } void SniperFlashHider() { src(2, 201005, 10); } void SMGSilencer() { src(2, 201006, 10); } void SniperSilencer() { src(2, 201007, 10); } void PistolSilencer() { src(2, 201008, 10); } void RifleCompensator() { src(2, 201009, 10); } void RifleFlashHider() { src(2, 201010, 10); } void RifleSilencer() { src(2, 201011, 10); } void Duckbill() { src(2, 201012, 10); } void AngledGrip() { src(2, 202001, 10); } void VerticalGrip() { src(2, 202002, 10); } void LightGrip() { src(2, 202004, 10); } void HalfGrip() { src(2, 202005, 10); } void ThumbGrip() { src(2, 202006, 10); } void LaserSight() { src(2, 202007, 10); } void RedDot() { src(2, 203001, 10); } void Holographic() { src(2, 203002, 10); } void Scope2x() { src(2, 203003, 10); } void Scope4x() { src(2, 203004, 10); } void Scope8x() { src(2, 203005, 10); } void CantedSight() { src(2, 203018, 10); } void PistolExtMag() { src(2, 204001, 10); } void PistolQuickMag() { src(2, 204002, 10); } void PistolQuickExtMag() { src(2, 204003, 10); } void SMGExtMag() { src(2, 204004, 10); } void SMGQuickMag() { src(2, 204005, 10); } void SMGQuickExtMag() { src(2, 204006, 10); } void SniperExtMag() { src(2, 204007, 10); } void SniperQuickMag() { src(2, 204008, 10); } void SniperQuickExtMag() { src(2, 204009, 10); } void ShotgunBulletLoops() { src(2, 204010, 10); } void RifleExtMag() { src(2, 204011, 10); } void RifleQuickMag() { src(2, 204012, 10); } void RifleQuickExtMag() { src(2, 204013, 10); } void Kar98kLoops() { src(2, 204014, 10); } void UziStock() { src(2, 205001, 10); } void TacticalStock() { src(2, 205002, 10); } void CheekPad() { src(2, 205003, 10); } void Quiver() { src(2, 205004, 10); } // 装备 - 类型5 (正确) void 夜视仪() { src(5, 504001, 10); } void HelmetLv3() { src(5, 502003, 10); } void VestLv3() { src(5, 503003, 10); } void BackpackLv3() { src(5, 501003, 10); } void HelmetLv1() { src(5, 502001, 10); } void VestLv1() { src(5, 503001, 10); } void BackpackLv1() { src(5, 501004, 10); } void HelmetLv2() { src(5, 502002, 10); } void VestLv2() { src(5, 503002, 10); } void BackpackLv2() { src(5, 501005, 10); } void ChristmasHelmet() { src(5, 502010, 10); } void BeastHelmet() { src(5, 502011, 10); } // 一键刷新所有皮肤武器 void SpawnAllSkinWeapons() { AKM_Chicheng(); AKM_Rongyao(); AKM_Wumujinwen(); AKM_Xueshi(); AKM_Kuangnu(); M16A4_Shachi(); M16A4_Qingyao(); M16A4_Wumujinwen(); M16A4_Huangshi(); M16A4_Yezhanyinghao(); M16A4_Kuangnu(); SCARL_Kuangnu(); SCARL_Wumujinwen(); SCARL_Chicheng(); SCARL_Xueshi(); M416_RocketGirl(); M416_Wumujinwen(); M416_Kuishe(); M416_Tuya(); M416_Shamofengbao(); M416_Xueyumicai(); M416_Xueshi(); M416_Chicheng(); M416_Spring(); GROZA_Kuangnu(); AUG_Xueshi(); UZI_Kuangnu(); Kar98K_Qingyao(); Kar98K_Wumujinwen(); Kar98K_FireLava(); Kar98K_Xueshi(); Kar98K_Spring(); AWM_Rainbow(); Crowbar_RedNight(); Pan_DoubleYolk(); Pan_Survivor(); Pan_NoHunt(); Pan_RottenTomato(); Pan_Forward(); Pan_RedNight(); } void 一键生成其他物资() { 红包(); 坚甲(); 利爪(); 小鸡(); 鸡蛋(); 南瓜(); 圣诞糖果(); 西瓜(); 小黄鸭(); 鸡(); 机密情报(); 鸡神奖杯(); 胜利手雷(); 足球(); 震爆弹(); 烟雾弹(); 燃烧瓶(); 破片手榴弹(); 跳舞弹(); 大春雷(); 鞭炮(); 小春雷(); 南瓜炸弹(); 苹果(); 圣诞玩具苹果(); 圣诞小鸡玩偶(); 冬季雪球(); 肾上腺素(); Q币(); 现金(); 点券(); 新年爆竹(); 新年烟花(); } void 一键生成衣服() { 雪地吉利服();晶翼女神套装();黑曜金尊套装();火箭少女101();至尊金龙外套();S1战斗裤();S1战斗外套();小黄衣();小黄裤();黑色连帽大衣();西部牛仔面罩();黑色rock();青色面罩();师傅专用外套();时尚圣诞套装();卡路里套装(); } void 一键生成动作() { 你好(); 感谢(); 鼓掌(); 大笑(); 来这里(); 走(); 否定(); 肯定(); 投降(); 愤怒(); 摇摆舞(); 电摇(); 拍灰舞(); 俄舞(); 安静(); 雀跃(); 崩溃(); 海带舞(); 街舞(); 壁虎步(); 机械舞(); 蹦迪舞(); 斗舞(); 秀舞(); 拉票舞(); 创造舞(); 三连赞(); 桑巴舞(); 空翻(); 摇篮舞(); 摆裙舞(); 吃鸡舞(); 抖胸舞(); 青蛙舞(); 甩手舞(); 点赞(); 欢庆舞(); 螃蟹舞(); 快看我(); 难过(); 扭秧歌(); 拜年男(); 红包来了(); 拜年女(); } void SpawnAllWeapons() { AKM(); M416(); AWM(); M16A4(); GROZA(); SCARL(); AUG(); QBZ(); M762(); MK47(); G36C(); UZI(); UMP9(); Vector(); Thompson(); PP19(); Kar98K(); M24(); SKS(); VSS(); Mini14(); Mk14(); Win94(); SLR(); QBU(); S686(); S1897(); S12K(); M249(); DP28(); P92(); P1911(); R1895(); P18C(); R45(); SawedOff(); SignalGun(); Scorpion(); ChickenFirework(); LanternFirework(); BeastSignal(); ChristmasSignal(); NewYearFirework(); Crossbow(); RiotShield(); Machete(); Crowbar(); Sickle(); Pan(); } void SpawnAllAmmo() { Bullet762(); Bullet556(); ShotgunShell(); Bullet45(); Magnum(); SignalFlare(); Arrow(); FireworkShell(); BeastBait(); } void SpawnAllAttachments() { Choke(); SMGCompensator(); SniperCompensator(); SMGFlashHider(); SniperFlashHider(); SMGSilencer(); SniperSilencer(); PistolSilencer(); RifleCompensator(); RifleFlashHider(); RifleSilencer(); Duckbill(); AngledGrip(); VerticalGrip(); LightGrip(); HalfGrip(); ThumbGrip(); LaserSight(); RedDot(); Holographic(); Scope2x(); Scope4x(); Scope8x(); CantedSight(); PistolExtMag(); PistolQuickMag(); PistolQuickExtMag(); SMGExtMag(); SMGQuickMag(); SMGQuickExtMag(); SniperExtMag(); SniperQuickMag(); SniperQuickExtMag(); ShotgunBulletLoops(); RifleExtMag(); RifleQuickMag(); RifleQuickExtMag(); Kar98kLoops(); UziStock(); TacticalStock(); CheekPad(); Quiver(); } void SpawnAllGear() { HelmetLv3(); VestLv3(); BackpackLv3(); HelmetLv1(); VestLv1(); BackpackLv1(); 夜视仪(); HelmetLv2(); VestLv2(); BackpackLv2(); ChristmasHelmet(); BeastHelmet(); } void SpawnItemM1(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=501003; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItemM2(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=502003; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItemM3(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=503003; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItemM4(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=404049; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItemM5(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=403124; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItemM6(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=404001; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItemM7(){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=5; Item.TypeSpecificID=403017; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(1); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } void SpawnItem(int ItemID,int ItemType,int Count){ 获取对象(); FTransform Transform; if(PlayerCharacter){ Transform=PlayerCharacter->GetTransform(); } AActor*Actor=UGameplayStatics::BeginSpawningActorFromClass(GetWorld(),APickUpWrapperActor::StaticClass(),Transform,true,UGameplayStatics::GetPlayerController(GetWorld(),0)); APickUpWrapperActor*PickUpActor=reinterpret_cast(Actor); if(PickUpActor){ FItemDefineID Item; Item.Type=ItemType; Item.TypeSpecificID=ItemID; PickUpActor->SetDefineID(Item); PickUpActor->SetCountOnServerAfterSpawn(Count); PickUpActor->ShowMesh(true); PickUpActor->ShowActor(); UGameplayStatics::FinishSpawningActor(PickUpActor,Transform); PickUpActor->RegisterToPlayerPickUpList(); } } static bool bDisableTimeouts = false; // 默认启用超时检查 // 判断物品类型 int getItemType(int itemID) { // 1. 货币类 (1000-1015) if (itemID >= 1000 && itemID <= 1015) { return 100; } // 2. 武器类 (101001-108004) if ((itemID >= 101001 && itemID <= 101010) || // 突击步枪 (itemID >= 102001 && itemID <= 102006) || // 冲锋枪 (itemID >= 103001 && itemID <= 103010) || // 狙击枪 (itemID >= 104001 && itemID <= 104003) || // 霰弹枪 (itemID >= 105001 && itemID <= 105002) || // 轻机枪 (itemID >= 106001 && itemID <= 106099) || // 手枪/特殊武器 (itemID == 107001 || itemID == 107003) || // 十字弩/防爆盾 (itemID >= 108001 && itemID <= 108004)) { // 近战武器 return 1; } // 3. 配件类 (201001-296008) if ((itemID >= 201001 && itemID <= 201012) || // 枪口类 (itemID >= 202001 && itemID <= 202007) || // 握把类 (itemID >= 203001 && itemID <= 203018) || // 瞄准镜类 (itemID >= 203104 && itemID <= 203104) || // 瞄准镜测试皮肤 (itemID >= 204001 && itemID <= 204014) || // 弹匣类 (itemID >= 205001 && itemID <= 205006) || // 枪托类 (itemID >= 281002 && itemID <= 281004) || // 默认枪口 (itemID >= 283009 && itemID <= 283010) || // 默认枪口 (itemID >= 291001 && itemID <= 291010) || // 突击步枪默认弹匣 (itemID >= 292001 && itemID <= 292006) || // 冲锋枪默认弹匣 (itemID >= 293002 && itemID <= 293010) || // 狙击枪默认弹匣 (itemID >= 294003 && itemID <= 294003) || // 霰弹枪默认弹匣 (itemID >= 295001 && itemID <= 295002) || // 轻机枪默认弹匣 (itemID >= 296001 && itemID <= 296008)) { // 手枪默认弹匣 return 2; } // 4. 弹药类 (301001-308003) if ((itemID >= 301001 && itemID <= 301001) || // 9毫米子弹 (itemID >= 302001 && itemID <= 302001) || // 7.62毫米子弹 (itemID >= 303001 && itemID <= 303001) || // 5.56毫米子弹 (itemID >= 304001 && itemID <= 304001) || // 12口径霰弹 (itemID >= 305001 && itemID <= 305001) || // .45口径子弹 (itemID >= 306001 && itemID <= 306001) || // .300马格南子弹 (itemID >= 307001 && itemID <= 307001) || // 弩箭 (itemID >= 308001 && itemID <= 308003)) { // 信号弹/烟花弹/年兽诱饵弹 return 3; } // 5. 服装类 (400997-407008) if ((itemID >= 400997 && itemID <= 400999) || // 创建头 (itemID >= 401003 && itemID <= 401992) || // 帽子类 (itemID >= 401992001 && itemID <= 401992002) || // 经典脸型体验 (itemID >= 401993 && itemID <= 401999) || // 经典脸型 (itemID >= 402001 && itemID <= 402079) || // 面罩/眼镜类 (itemID >= 403001 && itemID <= 403999) || // 上衣类 (itemID >= 404001 && itemID <= 404231) || // 下装类 (itemID >= 405001 && itemID <= 405999) || // 鞋子类 (itemID >= 406001 && itemID <= 406003) || // 头发 (itemID >= 406001001 && itemID <= 406001002) || // 经典发型体验 (itemID >= 40601001 && itemID <= 40606009) || // 经典发型 (itemID >= 407001001 && itemID <= 407001004) || // 脸涂 (itemID >= 407008 && itemID <= 407008) || // 海岛探路者墨镜 (itemID >= 410001 && itemID <= 410039) || // 套装类 (itemID >= 453001 && itemID <= 455003) || // 合作定制服装 (itemID >= 473001 && itemID <= 474009)) { // 腾讯系定制服装 return 4; } // 6. 防具/背包类 (501001-504001) if ((itemID >= 501001 && itemID <= 501006) || // 背包 (itemID >= 502001 && itemID <= 502011) || // 头盔 (itemID >= 503001 && itemID <= 503003) || // 防弹衣 (itemID >= 504001 && itemID <= 504001)) { // 夜视仪 return 5; } // 7. 消耗品类 (601001-603001) if ((itemID >= 601001 && itemID <= 601061) || // 医疗品 (itemID >= 602001 && itemID <= 602014) || // 投掷物 (itemID >= 603001 && itemID <= 603001)) { // 燃料 return 6; } // 8. 降落伞类 (701001-703086) if ((itemID >= 701001 && itemID <= 703086)) { return 4; // 注意:根据文件,降落伞也是类型4 } // 9. 宝箱/礼盒类 (1500001-1601002) if ((itemID >= 1500001 && itemID <= 1500008) || // 军备宝箱 (itemID >= 1501001 && itemID <= 1514005) || // 各种宝箱礼盒 (itemID == 1601002)) { // 改名卡 return 15; } // 10. 道具/材料类 (1601001-1602118) if ((itemID == 1601001) || // 重置角色卡 (itemID >= 1602001 && itemID <= 1602118)) { // 各种道具材料 return 16; } // 11. 军团相关 (1701001) if (itemID == 1701001) { return 17; } // 12. 头像框类 (2001001-2004308) if ((itemID >= 2001001 && itemID <= 2004308)) { return 20; } // 13. 经验/金币卡类 (2101001-2105001) if ((itemID >= 2101001 && itemID <= 2105001)) { return 21; } // 14. 表情动作类 (2200101-2204401) if ((itemID >= 2200101 && itemID <= 2204401)) { return 22; } // 15. 时效房卡类 (2401001-2408055) if ((itemID >= 2401001 && itemID <= 2408055)) { return 24; } // 16. 模式体验房卡类 (2501001-2508001) if ((itemID >= 2501001 && itemID <= 2508001)) { return 25; } // 17. 特效道具类 (3000301-3002002) if ((itemID >= 3000301 && itemID <= 3002002)) { return 30; } // 18. 浇水完成证明类 (4001001-4001006) if ((itemID >= 4001001 && itemID <= 4001006)) { return 40; } // 19. 武器皮肤配件 (100100101-200400103) if ((itemID >= 100100101 && itemID <= 100400903) || // M416等武器皮肤配件 (itemID >= 200200101 && itemID <= 200400103)) { // UMP9等武器皮肤配件 return 2; // 注意:根据文件,这些是类型2 } // 20. 武器皮肤 (101001001-108004006) if ((itemID >= 101001001 && itemID <= 108004006)) { return 1; // 注意:根据文件,武器皮肤是类型1 } // 默认返回1(武器类) return 1; } #undef bind // fix NDK macro collision with std::bind using namespace std; #define STATUS_ICON_RUNNING "◆" // 实心圆 #define STATUS_ICON_STOPPED "◆" // 空心圆 static std::mutex g_log_mutex; static std::vector g_log_lines; static const size_t MAX_LOG_LINES = 2000; static bool g_AutoWeaponFixEnabled = false; static bool enabled = false; class UDPProxy { public: UDPProxy(int local_port=7788, const std::string &target_ip="192.168.100.100", int target_port=7777) : local_port(local_port), target_ip(target_ip), target_port(target_port), sockfd(-1), running(false) {} ~UDPProxy() { stop(); } bool start() { if (running.load()) return true; // 创建新的日志文件名 { auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::tm tm = *std::localtime(&t); char buf[128]; snprintf(buf, sizeof(buf), "/sdcard/udp_proxy_%04d%02d%02d_%02d%02d%02d.log", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); logfile = buf; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { push_log(std::string("[ERR] socket create failed: ") + strerror(errno)); return false; } int opt = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(local_port); if (::bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { push_log(std::string("[ERR] bind failed: ") + strerror(errno)); close(sockfd); sockfd = -1; return false; } // 日志头 { std::ofstream f(logfile, std::ios::app); if (f.is_open()) { f << std::string(80, '=') << "\nUDP代理日志 - 启动时间: " << timestamp_date() << "\n监听端口: " << local_port << " -> 目标地址: " << target_ip << ":" << target_port << "\n" << std::string(80, '=') << "\n\n"; } } running.store(true); worker = std::thread(&UDPProxy::recv_loop, this); push_log(std::string("[启动] 监听 ") + std::to_string(local_port) + " -> 转发到 " + target_ip + ":" + std::to_string(target_port)); return true; } void stop() { if (!running.load()) return; running.store(false); if (sockfd != -1) { close(sockfd); sockfd = -1; } if (worker.joinable()) worker.join(); push_log(std::string("[STOP] 服务端已关闭")); } bool is_running() const { return running.load(); } void get_logs(std::vector& out) { std::lock_guard lk(log_mutex); out = logs; } private: int local_port; std::string target_ip; int target_port; int sockfd; std::atomic running; std::thread worker; std::mutex log_mutex; std::vector logs; std::mutex clients_mutex; std::map, long long> client_timestamps; std::string logfile; // 时间函数 static std::string timestamp_ms() { using namespace std::chrono; auto now = system_clock::now(); auto ms = duration_cast(now.time_since_epoch()) % 1000; auto t = system_clock::to_time_t(now); std::tm tm = *std::localtime(&t); char buf[64]; snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03lld", tm.tm_hour, tm.tm_min, tm.tm_sec, (long long)ms.count()); return buf; } static std::string timestamp_date() { auto t = std::time(nullptr); std::tm tm = *std::localtime(&t); char buf[64]; snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); return buf; } static std::string to_hex(const uint8_t *buf, size_t len) { std::ostringstream oss; oss << std::hex << std::setfill('0'); for (size_t i = 0; i < len; ++i) oss << std::setw(2) << (int)(buf[i] & 0xFF); return oss.str(); } void push_log(const std::string &s) { std::lock_guard lk(log_mutex); logs.push_back(s); if (logs.size() > 2000) logs.erase(logs.begin(), logs.begin() + (logs.size() - 2000)); std::ofstream f(logfile, std::ios::app); if (f.is_open()) f << s << "\n"; } void push_packet_log(const std::string &direction, double delay, ssize_t len, const std::string &ip, int port, const std::string &hexdata) { std::ostringstream ss; ss << timestamp_ms() << " | " << direction << " | 延迟: " << std::fixed << std::setprecision(2) << delay << "ms | 长度: " << len << "字节 | 地址: " << ip << ":" << port; push_log(ss.str()); push_log("原始数据: " + hexdata); } void recv_loop() { while (running.load()) { sockaddr_in addr; socklen_t addrlen = sizeof(addr); uint8_t buf[65536]; ssize_t len = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &addrlen); if (len < 0) { if (!running.load()) break; push_log(std::string("[ERR] recvfrom failed: ") + strerror(errno)); continue; } auto t0 = std::chrono::high_resolution_clock::now(); char ipbuf[64]; inet_ntop(AF_INET, &addr.sin_addr, ipbuf, sizeof(ipbuf)); int port = ntohs(addr.sin_port); bool from_client = (port != target_port); if (from_client) { { std::lock_guard lk(clients_mutex); client_timestamps[{ipbuf, port}] = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); } sockaddr_in target{}; target.sin_family = AF_INET; inet_pton(AF_INET, target_ip.c_str(), &target.sin_addr); target.sin_port = htons(target_port); sendto(sockfd, buf, len, 0, (struct sockaddr*)&target, sizeof(target)); auto t1 = std::chrono::high_resolution_clock::now(); double delay = std::chrono::duration(t1 - t0).count(); push_packet_log("客户端->服务端", delay, len, ipbuf, port, to_hex(buf, len)); } else { std::pair latest; bool found = false; { std::lock_guard lk(clients_mutex); long long best = 0; for (auto &kv : client_timestamps) { if (kv.second > best) { best = kv.second; latest = kv.first; found = true; } } } if (found) { sockaddr_in dst{}; dst.sin_family = AF_INET; inet_pton(AF_INET, latest.first.c_str(), &dst.sin_addr); dst.sin_port = htons(latest.second); sendto(sockfd, buf, len, 0, (struct sockaddr*)&dst, sizeof(dst)); auto t1 = std::chrono::high_resolution_clock::now(); double delay = std::chrono::duration(t1 - t0).count(); push_packet_log("服务端->客户端", delay, len, latest.first, latest.second, to_hex(buf, len)); } } } } }; static UDPProxy* g_proxy = nullptr; extern "C" bool StartPacketProxy() { if (g_proxy && g_proxy->is_running()) return true; g_proxy = new UDPProxy(); return g_proxy->start(); } extern "C" void StopPacketProxy() { if (g_proxy) { g_proxy->stop(); delete g_proxy; g_proxy = nullptr; } } extern "C" void GetPacketProxyLogs(std::vector& out) { if (g_proxy) g_proxy->get_logs(out); } ///===========抓包结束=========/// inline void push_log(const string &s) { std::lock_guard lk(g_log_mutex); if (g_log_lines.size() >= MAX_LOG_LINES) { g_log_lines.erase(g_log_lines.begin(), g_log_lines.begin() + (g_log_lines.size() - MAX_LOG_LINES + 1)); } g_log_lines.push_back(s); std::cout << s << std::endl; } static string bytes_to_hex_lower(const uint8_t *buf, size_t len) { std::ostringstream oss; oss << std::hex << std::setfill('0'); for (size_t i = 0; i < len; ++i) { oss << std::setw(2) << (int)(buf[i] & 0xFF); } string s = oss.str(); std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } static vector hex_to_bytes(const string &hex_in) { string filtered; filtered.reserve(hex_in.size()); for (char c : hex_in) { if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) filtered.push_back(c); } if (filtered.size() % 2 == 1) filtered.insert(filtered.begin(), '0'); vector out; out.reserve(filtered.size()/2); for (size_t i = 0; i + 1 < filtered.size(); i += 2) { unsigned int byte = 0; std::stringstream ss; ss << std::hex << filtered.substr(i,2); ss >> byte; out.push_back(static_cast(byte & 0xFF)); } return out; } static string current_time_str() { using namespace std::chrono; auto now = system_clock::now(); auto t = system_clock::to_time_t(now); std::tm tm = *std::localtime(&t); char buf[64]; auto ms = duration_cast(now.time_since_epoch()).count() % 1000; std::snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03lld", tm.tm_hour, tm.tm_min, tm.tm_sec, (long long)ms); return string(buf); } class GameUDPProxy { private: // 成员变量 int listen_port; std::string target_host; int target_port; std::string log_file; std::atomic running; // 改为 atomic int sockfd; sockaddr_in client_address; std::thread worker; // 添加线程成员 // 响应数据存储 std::vector> response_data; size_t response_index; std::string current_map; public: GameUDPProxy(int listen_port=7788, const std::string &target_host="127.0.0.1", int target_port=7777, const std::string &log_file="") : listen_port(listen_port), target_host(target_host), target_port(target_port), log_file(log_file), running(false), sockfd(-1), response_index(0), current_map("无") { // 构造函数中不自动加载数据 } ~GameUDPProxy() { stop(); } bool start() { if (running.load()) return true; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { push_log(std::string("[错误] 套接字创建失败: ") + strerror(errno)); return false; } int opt = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(listen_port); if (::bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { push_log(std::string("[错误] 绑定失败: ") + strerror(errno)); close(sockfd); sockfd = -1; return false; } running.store(true); // 启动日志头 push_log(repeat_string("=", 80)); push_log(std::string("UDP代理启动 - 时间: ") + get_current_time()); push_log(std::string("监听端口: ") + std::to_string(listen_port) + " -> 目标地址: " + target_host + ":" + std::to_string(target_port)); push_log(std::string("当前地图数据: ") + current_map); push_log(repeat_string("=", 80)); push_log("代理服务已启动,等待客户端连接..."); // 在新线程中运行 worker = std::thread(&GameUDPProxy::run, this); return true; } void stop() { running.store(false); if (sockfd != -1) { close(sockfd); sockfd = -1; } if (worker.joinable()) { worker.join(); } push_log("代理服务已停止"); } bool is_running() const { return running.load(); } // 设置地图数据 bool set_map_data(const std::string& map_choice) { std::map map_files = { {"1", "训练场"}, {"2", "海岛"}, {"3", "雪地"}, {"4", "雨林"}, {"5", "沙漠"} }; if (map_files.find(map_choice) != map_files.end()) { current_map = map_files[map_choice]; // 根据选择设置对应的数据 const char* log_data = nullptr; if (map_choice == "1") { log_data = TRAINING_LOG_DATA; } else if (map_choice == "2") { log_data = ISLAND_LOG_DATA; } else if (map_choice == "3") { log_data = SNOW_LOG_DATA; }else if (map_choice == "4") { log_data = YULINH_LOG_DATA; }else if (map_choice == "5") { log_data = SANOP_LOG_DATA; } response_data.clear(); // 清空原有数据 response_index = 0; if (log_data) { load_response_data_from_string(log_data); // 立即在日志中显示地图切换信息 std::ostringstream ss; ss << "已切换到地图: " << current_map << " (数据条数: " << response_data.size() << ")"; push_log(ss.str()); return true; } } return false; } std::string get_current_map() const { return current_map; } private: // 从字符串加载响应数据 void load_response_data_from_string(const char* log_content) { std::istringstream iss(log_content); std::string line; // 解析服务端->客户端的数据 std::vector lines; while (std::getline(iss, line)) { lines.push_back(line); } for (size_t i = 0; i < lines.size(); i++) { if (lines[i].find("服务端->客户端") != std::string::npos && i + 1 < lines.size()) { if (lines[i + 1].find("原始数据:") != std::string::npos) { size_t pos = lines[i + 1].find("原始数据: "); if (pos != std::string::npos) { std::string hex_data = lines[i + 1].substr(pos + 10); // 移除可能的空格 hex_data.erase(std::remove(hex_data.begin(), hex_data.end(), ' '), hex_data.end()); try { auto bytes = hex_to_bytes(hex_data); if (!bytes.empty()) { response_data.push_back(bytes); } } catch (...) { push_log("[错误] 解析十六进制数据失败: " + hex_data); } } } } } } // 根据客户端数据获取对应的服务端响应 std::vector get_response_for_client(const std::vector& client_data) { if (response_data.empty()) { // 如果没有预加载的数据,返回默认响应 return hex_to_bytes("19137909a95516a2a40ba6feb8f8c91c94d7388ee999a66004"); } // 简单策略:轮询返回预加载的响应数据 response_index = (response_index + 1) % response_data.size(); return response_data[response_index]; } void run() { while (running.load()) { sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); uint8_t buffer[4096]; // 设置超时,避免阻塞无法退出 struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); ssize_t len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &client_len); if (len < 0) { if (!running.load()) break; if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; } if (errno != EAGAIN && errno != EWOULDBLOCK) { push_log(std::string("[错误] 接收数据失败: ") + strerror(errno)); } continue; } if (len == 0) { continue; } client_address = client_addr; // 记录客户端消息 std::vector data(buffer, buffer + len); log_packet("客户端->服务端", 0.24, len, client_addr, data); // 处理客户端请求并发送响应 handle_client_request(data, client_addr); } } void handle_client_request(const std::vector& client_data, const sockaddr_in& client_addr) { try { // 获取对应的服务端响应 auto response_data_vec = get_response_for_client(client_data); // 模拟网络延迟 std::this_thread::sleep_for(std::chrono::milliseconds(45)); // 发送响应 ssize_t sent = sendto(sockfd, response_data_vec.data(), response_data_vec.size(), 0, (struct sockaddr*)&client_addr, sizeof(client_addr)); if (sent > 0) { // 记录服务端响应 log_packet("服务端->客户端", 0.33, response_data_vec.size(), client_addr, response_data_vec); } else { push_log(std::string("[错误] 发送响应失败: ") + strerror(errno)); } } catch (const std::exception& e) { push_log(std::string("[错误] 处理客户端请求失败: ") + e.what()); } } // 记录数据包日志 void log_packet(const std::string& direction, double delay, size_t len, const sockaddr_in& addr, const std::vector& data) { char ipbuf[64]; inet_ntop(AF_INET, &addr.sin_addr, ipbuf, sizeof(ipbuf)); int port = ntohs(addr.sin_port); std::ostringstream ss; ss << current_time_str() << " | " << direction << " | 延迟: " << std::fixed << std::setprecision(2) << delay << "ms | 长度: " << len << "字节 | 地址: " << ipbuf << ":" << port; push_log(ss.str()); push_log("原始数据: " + bytes_to_hex_lower(data.data(), data.size())); push_log(repeat_string("-", 60)); } // 获取当前时间字符串(带毫秒) std::string current_time_str() { auto now = std::chrono::system_clock::now(); auto ms = std::chrono::duration_cast( now.time_since_epoch()) % 1000; auto t = std::chrono::system_clock::to_time_t(now); std::tm tm = *std::localtime(&t); char buf[64]; std::snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03lld", tm.tm_hour, tm.tm_min, tm.tm_sec, (long long)ms.count()); return std::string(buf); } // 获取当前日期时间字符串 std::string get_current_time() { auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::tm tm = *std::localtime(&t); char buf[64]; std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); return std::string(buf); } // 字符串重复辅助函数 std::string repeat_string(const std::string& str, int n) { std::string result; for (int i = 0; i < n; ++i) { result += str; } return result; } }; // 全局代理实例 static GameUDPProxy* g_proxy_server = nullptr; // 启动代理服务 extern "C" bool StartEmbeddedUDPServer() { if (g_proxy_server && g_proxy_server->is_running()) return true; try { // 如果还没有创建实例,先创建 if (!g_proxy_server) { g_proxy_server = new GameUDPProxy(7788, "127.0.0.1", 7777, ""); } return g_proxy_server->start(); } catch (...) { push_log("[错误] 启动嵌入式服务器异常"); return false; } } // 停止代理服务 extern "C" void StopEmbeddedUDPServer() { try { if (g_proxy_server) { g_proxy_server->stop(); delete g_proxy_server; g_proxy_server = nullptr; } } catch (...) { push_log("[错误] 停止嵌入式服务器异常"); } } // 设置地图数据 extern "C" bool SetProxyMapData(const std::string& map_choice) { // 确保代理实例存在 if (!g_proxy_server) { g_proxy_server = new GameUDPProxy(7788, "127.0.0.1", 7777, ""); } return g_proxy_server->set_map_data(map_choice); } // 获取当前地图 extern "C" std::string GetProxyCurrentMap() { if (g_proxy_server) { return g_proxy_server->get_current_map(); } return "无"; } // 获取代理日志 extern "C" void GetEmbeddedLogs(std::vector& out_lines) { std::lock_guard lk(g_log_mutex); out_lines = g_log_lines; } // ==== Original main.cpp content follows ==== // ==================================================== // 车辆修复专用日志系统 - 独立于现有日志系统 // ==================================================== namespace VehicleFixLog { static std::vector LogEntries; static std::mutex LogMutex; static const int MAX_LOG_ENTRIES = 500; // 添加日志 void AddLog(const std::string& message) { std::lock_guard lock(LogMutex); // 获取当前时间 - 修复编译错误 time_t now = time(0); struct tm* tstruct = localtime(&now); if (tstruct) { char buf[80]; strftime(buf, sizeof(buf), "[%H:%M:%S] ", tstruct); std::string fullMessage = std::string(buf) + message; LogEntries.push_back(fullMessage); } else { LogEntries.push_back(message); } // 限制日志数量 if (LogEntries.size() > MAX_LOG_ENTRIES) { LogEntries.erase(LogEntries.begin()); } } // 清空日志 void ClearLogs() { std::lock_guard lock(LogMutex); LogEntries.clear(); } // 获取日志副本 std::vector GetLogs() { std::lock_guard lock(LogMutex); return LogEntries; } // 获取最近N条日志 std::vector GetRecentLogs(int count) { std::lock_guard lock(LogMutex); if (LogEntries.size() <= count) { return LogEntries; } return std::vector(LogEntries.end() - count, LogEntries.end()); } } // 车辆修复日志宏 #define VEHICLE_LOG(...) \ do { \ char buffer[512]; \ snprintf(buffer, sizeof(buffer), __VA_ARGS__); \ VehicleFixLog::AddLog(buffer); \ } while(0) // 错误处理函数 void HandleVehicleFixError(const std::string& errorMessage, SDK::ASTExtraBaseCharacter* Char = nullptr, SDK::ASTExtraVehicleBase* Vehicle = nullptr) { std::string errorLog = "[错误] "; errorLog += errorMessage; if (Char) { errorLog += " | 角色: "; if (Char->PlayerState) { errorLog += Char->PlayerState->PlayerName.ToString(); } else { errorLog += "未知"; } } if (Vehicle) { char addrBuffer[20]; snprintf(addrBuffer, sizeof(addrBuffer), "%p", Vehicle); errorLog += " | 车辆地址: "; errorLog += addrBuffer; } VEHICLE_LOG("%s", errorLog.c_str()); } // ==================================================== // 车辆修复系统数据结构 // ==================================================== struct PlayerInfo { SDK::APlayerState* PS; std::string Name; int UID; SDK::ASTExtraBaseCharacter* Character; // --- 车辆信息 --- bool bInVehicle = false; SDK::ASTExtraVehicleBase* Vehicle = nullptr; int VehicleSeatIdx = -1; }; std::vector RegisteredPlayers; // 状态跟踪 std::map LastSeatIndices; std::map LastVehicles; std::map PlayerInVehicleState; // ==================================================== // 辅助函数 // ==================================================== // 辅助函数:构建座位Socket名称 std::string GetSeatSocketName(int SeatIndex) { if (SeatIndex == 0) return "seat_driver"; else return "seat_passenger_" + std::to_string(SeatIndex); } inline std::string GetObjectClassNameEx(UObject* Object) { if (!Object) return "NULL_OBJ"; if (!Object->ClassPrivate) return "NULL_CLASS"; try { return Object->ClassPrivate->NamePrivate.GetName(); } catch (...) { return "ERR"; } } // ==================================================== // 玩家管理函数 // ==================================================== void RegisterPlayer(SDK::APlayerState* PS, SDK::ASTExtraBaseCharacter* C) { PlayerInfo info; info.PS = PS; info.Name = PS->PlayerName.ToString(); info.UID = PS->PlayerID; info.Character = C; info.Vehicle = C->CurrentVehicle; info.VehicleSeatIdx = C->VehicleSeatIdx; info.bInVehicle = (C->CurrentVehicle != nullptr); RegisteredPlayers.push_back(info); VEHICLE_LOG("[玩家管理] 注册玩家: %s (UID: %d) | 车辆: %s | 座位: %d", info.Name.c_str(), info.UID, info.bInVehicle ? "是" : "否", info.VehicleSeatIdx); } bool IsHostPlayer(SDK::APlayerState* PS, SDK::UWorld* World) { if (!PS || !World) return false; auto* GI = World->OwningGameInstance; if (!GI || GI->LocalPlayers.Num() == 0) return false; auto* LocalPC = GI->LocalPlayers[0]->PlayerController; if (!LocalPC) return false; return PS->Owner == LocalPC; } SDK::ASTExtraBaseCharacter* GetCharacterFromController(SDK::APlayerController* PC) { if (!PC) { VEHICLE_LOG("[角色获取] 控制器为空指针"); return nullptr; } static SDK::ASTExtraPlayerController* CachedSTPC = nullptr; static SDK::ASTExtraBaseCharacter* CachedCharacter = nullptr; if (CachedSTPC == PC && CachedCharacter) return CachedCharacter; SDK::ASTExtraPlayerController* STPC = nullptr; if (PC->IsA(SDK::ASTExtraPlayerController::StaticClass())) { STPC = (SDK::ASTExtraPlayerController*)PC; if (STPC->STExtraBaseCharacter) { CachedSTPC = STPC; CachedCharacter = STPC->STExtraBaseCharacter; return CachedCharacter; } } SDK::ASTExtraBaseCharacter* fromUtil = SDK::USTExtraVehicleUtils::GetCharacter(STPC ? STPC : (SDK::ASTExtraPlayerController*)PC); if (fromUtil) { CachedSTPC = STPC; CachedCharacter = fromUtil; return fromUtil; } if (PC->Pawn && PC->Pawn->IsA(SDK::ASTExtraBaseCharacter::StaticClass())) { CachedSTPC = STPC; CachedCharacter = (SDK::ASTExtraBaseCharacter*)PC->Pawn; return CachedCharacter; } return nullptr; } bool IsKnown(SDK::APlayerState* ps) { for (size_t i = 0; i < RegisteredPlayers.size(); i++) { if (!RegisteredPlayers[i].PS) continue; if (RegisteredPlayers[i].PS == ps) return true; } return false; } inline float GetLocalTime() { static auto start_time = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now(); return std::chrono::duration(now - start_time).count(); } // ==================================================== // 车辆调试函数 // ==================================================== void DebugVehicleReplication(SDK::ASTExtraVehicleBase* Vehicle) { if (!Vehicle) { VEHICLE_LOG("[车辆调试] 车辆为空指针"); return; } VEHICLE_LOG("[车辆调试] 地址: %p | 引擎启动: %d | 反作弊: %d | 座位数量: %d", Vehicle, Vehicle->bIsEngineStarted, Vehicle->bEnableAntiCheat, (Vehicle->VehicleSeats ? Vehicle->VehicleSeats->SeatOccupiers.Num() : 0)); } // ==================================================== // 服务端车辆修复逻辑 // ==================================================== void ProcessServerVehicleFix(SDK::ASTExtraPlayerController* STEPC, SDK::ASTExtraBaseCharacter* Char, SDK::ASTExtraVehicleBase* State_Vehicle) { if (!STEPC) { HandleVehicleFixError("STEPC为空指针"); return; } if (!Char) { HandleVehicleFixError("角色为空指针"); return; } if (!State_Vehicle) { HandleVehicleFixError("车辆为空指针", Char); return; } if (!STEPC->VehicleUserComp) { HandleVehicleFixError("VehicleUserComp为空指针", Char, State_Vehicle); return; } // 确保VehicleUserComp的Character指向正确的角色 if (!STEPC->VehicleUserComp->Character && Char) { STEPC->VehicleUserComp->Character = (SDK::ASTExtraPlayerCharacter*)Char; VEHICLE_LOG("[服务端修复] 设置VehicleUserComp角色"); } /* // 调试信息:打印当前车辆状态 VEHICLE_LOG("[服务端修复] 玩家: %s | 车辆状态: %d | 当前座位: %d | 引擎已启动: %d", Char->PlayerState ? Char->PlayerState->PlayerName.ToString().c_str() : "未知", (int)STEPC->VehicleUserComp->VehicleUserState, Char->VehicleSeatIdx, State_Vehicle->bIsEngineStarted);*/ // 主要车辆修复逻辑 if (STEPC->VehicleUserComp->VehicleUserState == SDK::ESTExtraVehicleUserState::ESTExtraVehicleUserState__EVUS_AsDriver && State_Vehicle->VehicleSeats && State_Vehicle->VehicleSeats->SeatOccupiers.Num() > 0) { // 检查驾驶员座位是否为空 SDK::ASTExtraPlayerCharacter* CurrentDriver = State_Vehicle->VehicleSeats->SeatOccupiers[0]; if (CurrentDriver == nullptr) { // 驾驶员座位为空,执行完整的上车流程 VEHICLE_LOG("[服务端修复] 驾驶员座位为空,开始修复..."); // 1. 请求进入车辆 STEPC->VehicleUserComp->ReqEnterVehicle(State_Vehicle, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_DriversSeat); // 2. 设置座位占用者 State_Vehicle->VehicleSeats->SeatOccupiers[0] = (SDK::ASTExtraPlayerCharacter*)Char; // 3. 启动车辆引擎并禁用反作弊 State_Vehicle->bIsEngineStarted = true; State_Vehicle->bEnableAntiCheat = false; // 4. 调用车辆座位附加处理函数 State_Vehicle->HandleOnSeatAttached( (SDK::ASTExtraPlayerCharacter*)Char, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_DriversSeat, 0 ); // 5. 更新角色状态 Char->ForcePlayerUpdateAnimation(); Char->VehicleSeatIdx = 0; Char->bWasOnVehicle = true; Char->CurrentVehicle = State_Vehicle; // 6. 强制网络更新 Char->ForceNetUpdate(); State_Vehicle->ForceNetUpdate(); VEHICLE_LOG("[服务端修复] 驾驶员座位已修复并占用"); } else if (CurrentDriver != (SDK::ASTExtraPlayerCharacter*)Char) { // 驾驶员座位已被其他角色占用,处理座位冲突 VEHICLE_LOG("[服务端修复] 驾驶员座位已被其他玩家占用,尝试寻找空座位..."); // 寻找其他空座位 bool bFoundEmptySeat = false; for (int seatIdx = 1; seatIdx < State_Vehicle->VehicleSeats->SeatOccupiers.Num(); seatIdx++) { if (State_Vehicle->VehicleSeats->SeatOccupiers[seatIdx] == nullptr) { // 找到空座位,作为乘客上车 STEPC->VehicleUserComp->ReqEnterVehicle( State_Vehicle, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_PassengersSeat ); State_Vehicle->VehicleSeats->SeatOccupiers[seatIdx] = (SDK::ASTExtraPlayerCharacter*)Char; // 调用乘客座位附加处理 State_Vehicle->HandleOnSeatAttached( (SDK::ASTExtraPlayerCharacter*)Char, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_PassengersSeat, seatIdx ); Char->ForcePlayerUpdateAnimation(); Char->VehicleSeatIdx = seatIdx; Char->bWasOnVehicle = true; Char->CurrentVehicle = State_Vehicle; Char->ForceNetUpdate(); State_Vehicle->ForceNetUpdate(); VEHICLE_LOG("[服务端修复] 玩家已放置到乘客座位 %d", seatIdx); bFoundEmptySeat = true; break; } } if (!bFoundEmptySeat) { VEHICLE_LOG("[服务端修复] 没有可用空座位"); } } else { // 当前角色已经是驾驶员,确保状态正确 Char->CurrentVehicle = State_Vehicle; Char->bWasOnVehicle = true; Char->ForceNetUpdate(); State_Vehicle->ForceNetUpdate(); VEHICLE_LOG("[服务端修复] 玩家已经是驾驶员,状态已更新"); } } else if (STEPC->VehicleUserComp->VehicleUserState == SDK::ESTExtraVehicleUserState::ESTExtraVehicleUserState__EVUS_ASPassenger && State_Vehicle->VehicleSeats && State_Vehicle->VehicleSeats->SeatOccupiers.Num() > 0) { // 乘客状态逻辑 bool bIsInVehicle = false; int currentSeatIdx = -1; // 检查角色是否在车辆座位上 for (int seatIdx = 0; seatIdx < State_Vehicle->VehicleSeats->SeatOccupiers.Num(); seatIdx++) { if (State_Vehicle->VehicleSeats->SeatOccupiers[seatIdx] == (SDK::ASTExtraPlayerCharacter*)Char) { bIsInVehicle = true; currentSeatIdx = seatIdx; break; } } if (bIsInVehicle) { // 角色在车辆上,确保状态正确 Char->VehicleSeatIdx = currentSeatIdx; Char->bWasOnVehicle = true; Char->CurrentVehicle = State_Vehicle; Char->ForceNetUpdate(); VEHICLE_LOG("[服务端修复] 玩家在乘客座位 %d,状态已更新", currentSeatIdx); } else { // 角色不在车辆上,尝试作为乘客上车 VEHICLE_LOG("[服务端修复] 玩家不在车辆上,尝试作为乘客上车..."); for (int seatIdx = 1; seatIdx < State_Vehicle->VehicleSeats->SeatOccupiers.Num(); seatIdx++) { if (State_Vehicle->VehicleSeats->SeatOccupiers[seatIdx] == nullptr) { STEPC->VehicleUserComp->ReqEnterVehicle( State_Vehicle, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_PassengersSeat ); State_Vehicle->VehicleSeats->SeatOccupiers[seatIdx] = (SDK::ASTExtraPlayerCharacter*)Char; State_Vehicle->HandleOnSeatAttached( (SDK::ASTExtraPlayerCharacter*)Char, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_PassengersSeat, seatIdx ); Char->ForcePlayerUpdateAnimation(); Char->VehicleSeatIdx = seatIdx; Char->bWasOnVehicle = true; Char->CurrentVehicle = State_Vehicle; Char->ForceNetUpdate(); State_Vehicle->ForceNetUpdate(); VEHICLE_LOG("[服务端修复] 玩家已作为乘客进入座位 %d", seatIdx); break; } } } } else { // 不在车辆上的状态处理 - 修复枚举错误 VEHICLE_LOG("[服务端修复] 玩家不在车辆上,状态: %d", (int)STEPC->VehicleUserComp->VehicleUserState); if (Char->CurrentVehicle) { // 清理旧车辆座位 SDK::ASTExtraVehicleBase* OldVehicle = Char->CurrentVehicle; int OldSeatIdx = Char->VehicleSeatIdx; if (OldSeatIdx >= 0 && OldSeatIdx < OldVehicle->VehicleSeats->SeatOccupiers.Num()) { if (OldVehicle->VehicleSeats->SeatOccupiers[OldSeatIdx] == (SDK::ASTExtraPlayerCharacter*)Char) { OldVehicle->VehicleSeats->SeatOccupiers[OldSeatIdx] = nullptr; } } Char->CurrentVehicle = nullptr; Char->VehicleSeatIdx = -1; Char->bWasOnVehicle = false; Char->ForceNetUpdate(); OldVehicle->ForceNetUpdate(); VEHICLE_LOG("[服务端修复] 玩家已从车辆移除"); } } } // ==================================================== // 客户端车辆位置和视角修复 // ==================================================== void ProcessClientVehicleFix(SDK::ASTExtraPlayerController* STEPC, SDK::ASTExtraBaseCharacter* Char, SDK::ASTExtraVehicleBase* Vehicle, int SeatIdx, bool bIsLocalPlayer) { if (!STEPC) { HandleVehicleFixError("STEPC为空指针"); return; } if (!Char) { HandleVehicleFixError("角色为空指针"); return; } if (!Vehicle) { HandleVehicleFixError("车辆为空指针", Char); return; } bool bIsDriver = (SeatIdx == 0); // 只有本地玩家才执行客户端特定的修复 if (bIsLocalPlayer) { VEHICLE_LOG("[客户端修复] 本地玩家 | 座位: %d | 是驾驶员: %s", SeatIdx, bIsDriver ? "是" : "否"); // 1. 角色位置和附加修复 if (Vehicle->RootComponent) { // 先分离角色(如果已附加) Char->K2_DetachFromActor( (SDK::EDetachmentRule)1, (SDK::EDetachmentRule)1, (SDK::EDetachmentRule)1); // 使用K2_AttachToComponent将角色附加到车辆的根组件 SDK::FName SocketName = SDK::FName(); Char->K2_AttachToComponent(Vehicle->RootComponent, SocketName, (SDK::EAttachmentRule)1, (SDK::EAttachmentRule)1, (SDK::EAttachmentRule)1, false); // 设置相对位置和旋转 SDK::FTransform RelativeTransform; // 根据座位设置不同的相对位置 if (bIsDriver) { // 驾驶员位置:使用用户调节的偏移 RelativeTransform.Translation.X = 驾驶员X偏移; // 前方 RelativeTransform.Translation.Y = 驾驶员Y偏移; // 中心 RelativeTransform.Translation.Z = 驾驶员Z偏移; // 高度 } else { // 乘客位置:根据座位索引调整 RelativeTransform.Translation.X = 乘客X偏移; // 稍微靠前 RelativeTransform.Translation.Y = (SeatIdx % 2 == 0 ? 乘客Y偏移 : -乘客Y偏移); // 左右交替 RelativeTransform.Translation.Z = 乘客Z偏移; // 高度 } // 设置旋转 RelativeTransform.Rotation.X = 0.0f; RelativeTransform.Rotation.Y = 0.0f; RelativeTransform.Rotation.Z = 0.0f; RelativeTransform.Rotation.W = 1.0f; // 缩放 RelativeTransform.Scale3D.X = 1.0f; RelativeTransform.Scale3D.Y = 1.0f; RelativeTransform.Scale3D.Z = 1.0f; // 应用相对变换 SDK::FHitResult SweepHitResult; Char->K2_SetActorRelativeTransform(RelativeTransform, false, true, &SweepHitResult); // 更新座位索引 Char->VehicleSeatIdx = SeatIdx; VEHICLE_LOG("[客户端修复] 角色已附加到车辆,相对位置: (%.1f, %.1f, %.1f)", RelativeTransform.Translation.X, RelativeTransform.Translation.Y, RelativeTransform.Translation.Z); } // 2. 控制权转移 if (Char->Controller) { if (bIsDriver) { // 驾驶员:控制权转移给车辆 Char->Controller->Possess(Vehicle); // 设置摄像机跟随车辆 STEPC->SetViewTargetWithBlend(Vehicle, 0.2f, (SDK::EViewTargetBlendFunction)0, 0.0f, false); VEHICLE_LOG("[客户端修复] 控制权已转移给车辆"); } else { // 乘客:控制权保持在角色 Char->Controller->Possess(Char); // 设置摄像机跟随角色 STEPC->SetViewTargetWithBlend(Char, 0.2f, (SDK::EViewTargetBlendFunction)0, 0.0f, false); VEHICLE_LOG("[客户端修复] 控制权保持在角色"); } } // 3. 视角控制设置 - 修复视角滑动问题 STEPC->SetIgnoreLookInput(false); // 允许视角滑动 STEPC->ResetIgnoreLookInput(); // 重置视角输入 // STEPC->bIgnoreLookInput = false; // 直接设置成员变量 // 4. 鼠标控制设置 STEPC->bShowMouseCursor = false; // 隐藏鼠标光标 STEPC->bEnableClickEvents = false; // 禁用点击事件 STEPC->bEnableMouseOverEvents = false; // 禁用鼠标悬停事件 VEHICLE_LOG("[客户端修复] 视角控制已启用,鼠标控制已设置"); } } // ==================================================== // 客户端下车处理 // ==================================================== void ProcessClientExitVehicle(SDK::ASTExtraPlayerController* STEPC, SDK::ASTExtraBaseCharacter* Char, SDK::ASTExtraVehicleBase* OldVehicle, int OldSeatIdx, bool bIsLocalPlayer) { if (!STEPC) { HandleVehicleFixError("STEPC为空指针"); return; } if (!Char) { HandleVehicleFixError("角色为空指针"); return; } // 1. 分离角色 Char->K2_DetachFromActor( (SDK::EDetachmentRule)1, (SDK::EDetachmentRule)1, (SDK::EDetachmentRule)1); VEHICLE_LOG("[客户端修复] 角色已从车辆分离"); // 只有本地玩家需要处理控制权和摄像机 if (bIsLocalPlayer) { VEHICLE_LOG("[客户端修复] 本地玩家下车,原座位: %d", OldSeatIdx); // 2. 恢复控制权到角色 if (Char->Controller) { Char->Controller->Possess(Char); // 3. 设置摄像机跟随角色 STEPC->SetViewTargetWithBlend(Char, 0.2f, (SDK::EViewTargetBlendFunction)0, 0.0f, false); // 4. 重置视角控制 - 修复下车后视角问题 STEPC->SetIgnoreLookInput(false); STEPC->ResetIgnoreLookInput(); // STEPC->bIgnoreLookInput = false; // 5. 重置鼠标控制 STEPC->bShowMouseCursor = false; STEPC->bEnableClickEvents = false; STEPC->bEnableMouseOverEvents = false; VEHICLE_LOG("[客户端修复] 控制权已恢复,摄像机已重置"); } } // 6. 清理座位占用 if (OldVehicle && OldVehicle->VehicleSeats && OldSeatIdx >= 0 && OldSeatIdx < OldVehicle->VehicleSeats->SeatOccupiers.Num()) { if (OldVehicle->VehicleSeats->SeatOccupiers[OldSeatIdx] == (SDK::ASTExtraPlayerCharacter*)Char) { OldVehicle->VehicleSeats->SeatOccupiers[OldSeatIdx] = nullptr; OldVehicle->ForceNetUpdate(); VEHICLE_LOG("[客户端修复] 原座位 %d 已清空", OldSeatIdx); } } // 7. 强制下车请求 if (STEPC->VehicleUserComp) { SDK::FVector ClientVehicleVelocity = {0.0f, 0.0f, 0.0f}; STEPC->VehicleUserComp->ReqExitVehicle(ClientVehicleVelocity); VEHICLE_LOG("[客户端修复] 发送下车请求"); } // 8. 更新角色状态 Char->CurrentVehicle = nullptr; Char->VehicleSeatIdx = -1; Char->bWasOnVehicle = false; Char->ForceNetUpdate(); VEHICLE_LOG("[客户端修复] 玩家已完全下车"); } // ==================================================== // 客户端切换座位处理 // ==================================================== void ProcessClientSwitchSeat(SDK::ASTExtraPlayerController* STEPC, SDK::ASTExtraBaseCharacter* Char, SDK::ASTExtraVehicleBase* Vehicle, int OldSeatIdx, int NewSeatIdx, bool bIsLocalPlayer) { if (!STEPC) { HandleVehicleFixError("STEPC为空指针"); return; } if (!Char) { HandleVehicleFixError("角色为空指针"); return; } if (!Vehicle) { HandleVehicleFixError("车辆为空指针", Char); return; } if (!STEPC->VehicleUserComp) { HandleVehicleFixError("VehicleUserComp为空指针", Char, Vehicle); return; } VEHICLE_LOG("[客户端修复] 切换座位 从 %d 到 %d", OldSeatIdx, NewSeatIdx); // 1. 清理旧座位 if (OldSeatIdx >= 0 && OldSeatIdx < Vehicle->VehicleSeats->SeatOccupiers.Num()) { if (Vehicle->VehicleSeats->SeatOccupiers[OldSeatIdx] == (SDK::ASTExtraPlayerCharacter*)Char) { Vehicle->VehicleSeats->SeatOccupiers[OldSeatIdx] = nullptr; VEHICLE_LOG("[客户端修复] 旧座位 %d 已清空", OldSeatIdx); } } // 2. 请求进入新座位 if (NewSeatIdx == 0) { // 切换到驾驶员座位 STEPC->VehicleUserComp->ReqEnterVehicle( Vehicle, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_DriversSeat ); Vehicle->VehicleSeats->SeatOccupiers[0] = (SDK::ASTExtraPlayerCharacter*)Char; Vehicle->HandleOnSeatAttached( (SDK::ASTExtraPlayerCharacter*)Char, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_DriversSeat, 0 ); VEHICLE_LOG("[客户端修复] 已切换到驾驶员座位"); } else { // 切换到乘客座位 STEPC->VehicleUserComp->ReqEnterVehicle( Vehicle, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_PassengersSeat ); Vehicle->VehicleSeats->SeatOccupiers[NewSeatIdx] = (SDK::ASTExtraPlayerCharacter*)Char; Vehicle->HandleOnSeatAttached( (SDK::ASTExtraPlayerCharacter*)Char, SDK::ESTExtraVehicleSeatType::ESTExtraVehicleSeatType__ESeatType_PassengersSeat, NewSeatIdx ); VEHICLE_LOG("[客户端修复] 已切换到乘客座位 %d", NewSeatIdx); } // 3. 更新角色状态 Char->VehicleSeatIdx = NewSeatIdx; Char->CurrentVehicle = Vehicle; Char->bWasOnVehicle = true; Char->ForcePlayerUpdateAnimation(); // 4. 强制网络更新 Char->ForceNetUpdate(); Vehicle->ForceNetUpdate(); // 5. 客户端特定的位置和视角修复 ProcessClientVehicleFix(STEPC, Char, Vehicle, NewSeatIdx, bIsLocalPlayer); VEHICLE_LOG("[客户端修复] 座位切换完成"); } // ==================================================== // 服务端逻辑 // ==================================================== void ProcessServerLogic(SDK::UWorld* World, SDK::AGameStateBase* GS) { auto& Players = GS->PlayerArray; static float LastVehicleFixTime = 0.0f; float CurrentTime = GetLocalTime(); if (CurrentTime - LastVehicleFixTime < 1.0f) return; LastVehicleFixTime = CurrentTime; for (int i = 0; i < Players.Num(); i++) { SDK::APlayerState* PS = Players[i]; if (!PS) continue; if (IsHostPlayer(PS, World)) continue; if (!PS->Owner) continue; SDK::ASTExtraPlayerController* STEPC = nullptr; SDK::APlayerController* PC = (SDK::APlayerController*)PS->Owner; if (PS->Owner->IsA(SDK::ASTExtraPlayerController::StaticClass())) STEPC = (SDK::ASTExtraPlayerController*)PS->Owner; else if (PC && PC->IsA(SDK::ASTExtraPlayerController::StaticClass())) STEPC = (SDK::ASTExtraPlayerController*)PC; if (!STEPC) continue; SDK::ASTExtraBaseCharacter* Char = STEPC->STExtraBaseCharacter; if (!Char) Char = GetCharacterFromController(PC); if (!Char) continue; // 注册玩家 if (!IsKnown(PS)) RegisterPlayer(PS, Char); // 服务端车辆修复逻辑 if (!STEPC->VehicleUserComp) continue; SDK::ASTExtraVehicleBase* State_Vehicle = nullptr; if (STEPC->STExtraBaseCharacter && STEPC->STExtraBaseCharacter->CurrentVehicle) { State_Vehicle = STEPC->STExtraBaseCharacter->CurrentVehicle; } else if (PC->Pawn && PC->Pawn->IsA(SDK::ASTExtraVehicleBase::StaticClass())) { State_Vehicle = (SDK::ASTExtraVehicleBase*)PC->Pawn; } if (State_Vehicle) { ProcessServerVehicleFix(STEPC, Char, State_Vehicle); } } } // ==================================================== // 客户端逻辑 // ==================================================== void ProcessClientLogic(SDK::UWorld* World, SDK::AGameStateBase* GS) { auto& Players = GS->PlayerArray; static float LastClientUpdateTime = 0.0f; float CurrentTime = GetLocalTime(); if (CurrentTime - LastClientUpdateTime < 0.1f) return; LastClientUpdateTime = CurrentTime; // 获取本地玩家控制器 SDK::APlayerController* LocalPC = SDK::UGameplayStatics::GetPlayerController(World, 0); if (!LocalPC) return; for (int i = 0; i < Players.Num(); i++) { SDK::APlayerState* PS = Players[i]; if (!PS) continue; if (!PS->Owner) continue; SDK::ASTExtraPlayerController* STEPC = nullptr; SDK::APlayerController* PC = (SDK::APlayerController*)PS->Owner; if (PS->Owner->IsA(SDK::ASTExtraPlayerController::StaticClass())) STEPC = (SDK::ASTExtraPlayerController*)PS->Owner; else if (PC && PC->IsA(SDK::ASTExtraPlayerController::StaticClass())) STEPC = (SDK::ASTExtraPlayerController*)PC; if (!STEPC) continue; SDK::ASTExtraBaseCharacter* Char = STEPC->STExtraBaseCharacter; if (!Char) Char = GetCharacterFromController(PC); if (!Char) continue; // 判断是否是本地玩家 bool bIsLocalPlayer = (PC == LocalPC); // 客户端车辆控制逻辑 if (!STEPC->VehicleUserComp) continue; SDK::ASTExtraVehicleBase* Vehicle = Char->CurrentVehicle; if (!Vehicle && PC->Pawn && PC->Pawn->IsA(SDK::ASTExtraVehicleBase::StaticClass())) Vehicle = (SDK::ASTExtraVehicleBase*)PC->Pawn; int SeatIdx = Char->VehicleSeatIdx; int LastSeatIdx = -1; bool bWasInVehicle = false; // 获取上一次的座位索引和车辆状态 if (LastSeatIndices.find(PC) != LastSeatIndices.end()) { LastSeatIdx = LastSeatIndices[PC]; } if (PlayerInVehicleState.find(PC) != PlayerInVehicleState.end()) { bWasInVehicle = PlayerInVehicleState[PC]; } bool bCurrentlyInVehicle = (Vehicle != nullptr && SeatIdx >= 0); // 处理状态变化 if (bCurrentlyInVehicle) { // 角色在车辆上 if (!bWasInVehicle) { // 新上车 VEHICLE_LOG("[客户端修复] 新上车,座位: %d", SeatIdx); ProcessClientVehicleFix(STEPC, Char, Vehicle, SeatIdx, bIsLocalPlayer); } else if (LastSeatIdx != SeatIdx) { // 切换座位 VEHICLE_LOG("[客户端修复] 切换座位 从 %d 到 %d", LastSeatIdx, SeatIdx); ProcessClientSwitchSeat(STEPC, Char, Vehicle, LastSeatIdx, SeatIdx, bIsLocalPlayer); } else { // 保持原座位,修复位置和视角 ProcessClientVehicleFix(STEPC, Char, Vehicle, SeatIdx, bIsLocalPlayer); } } else if (bWasInVehicle) { // 刚下车 SDK::ASTExtraVehicleBase* LastVehicle = nullptr; if (LastVehicles.find(PC) != LastVehicles.end()) { LastVehicle = LastVehicles[PC]; } VEHICLE_LOG("[客户端修复] 下车,原座位: %d", LastSeatIdx); ProcessClientExitVehicle(STEPC, Char, LastVehicle, LastSeatIdx, bIsLocalPlayer); } // 更新状态记录 LastSeatIndices[PC] = SeatIdx; PlayerInVehicleState[PC] = bCurrentlyInVehicle; if (Vehicle) { LastVehicles[PC] = Vehicle; } else { // 确保不在车上时清空车辆记录 if (LastVehicles.find(PC) != LastVehicles.end()) { LastVehicles.erase(PC); } } } } // ==================================================== // 主逻辑处理函数 // ==================================================== void ProcessPlayers() { SDK::UWorld* World = GetWorld(); if (!World) { VEHICLE_LOG("[主逻辑] 世界为空指针"); return; } SDK::AGameStateBase* GS = World->GameState; if (!GS) { VEHICLE_LOG("[主逻辑] 游戏状态为空指针"); return; } static int frameCounter = 0; frameCounter++; // 每100帧记录一次状态 if (frameCounter % 100 == 0) { VEHICLE_LOG("[系统状态] 处理玩家数量: %d | 已注册玩家: %d", GS->PlayerArray.Num(), RegisteredPlayers.size()); } // 获取本地玩家控制器 SDK::APlayerController* MyController = SDK::UGameplayStatics::GetPlayerController(World, 0); if (MyController && MyController->HasAuthority()) { // 服务端逻辑 VEHICLE_LOG("[网络模式] 当前运行于: 服务端模式"); ProcessServerLogic(World, GS); } else { // 客户端逻辑:执行服务端和客户端逻辑 VEHICLE_LOG("[网络模式] 当前运行于: 客户端模式"); ProcessServerLogic(World, GS); // 客户端也执行服务端逻辑 ProcessClientLogic(World, GS); // 客户端执行客户端逻辑 } } // ==================== 头文件包含 ==================== #include #include #include #include #include #include #include // ==================== 玩家信息结构体 ==================== struct SimplePlayerInfo { SDK::ASTExtraBaseCharacter* PlayerCharacter; }; // ==================== 全局变量 ==================== static bool bIsTeleporting = false; static std::string sStatusMessage = ""; static float fStatusDisplayTime = 0.0f; static std::mutex g_TeleportMutex; static std::mutex g_WorldAccessMutex; static std::atomic s_TeleportCounter(0); // ==================== 辅助函数 ==================== // 创建零向量 SDK::FVector MakeZeroVector() { SDK::FVector vec; vec.X = 0.0f; vec.Y = 0.0f; vec.Z = 0.0f; return vec; } // 改进的指针有效性检查 template bool IsValidPointer(T* ptr) { if (!ptr) return false; // 检查指针是否指向有效地址范围(简化版) uintptr_t addr = reinterpret_cast(ptr); // 基本地址范围检查 if (addr < 0x10000 || addr > 0xFFFFFFFFFFFFFF00) return false; // 检查指针是否对齐(可选) if (addr % sizeof(void*) != 0) return false; return true; } // 检查基础指针(兼容旧代码) bool IsPointerValid(void* ptr) { return IsValidPointer(ptr); } // 获取服务端玩家位置 SDK::FVector GetServerPlayerPositionSafe() { std::lock_guard lock(g_WorldAccessMutex); try { SDK::UWorld* world = GetWorld(); if (!IsValidPointer(world)) return MakeZeroVector(); // 获取玩家控制器 SDK::APlayerController* playerCtrl = SDK::UGameplayStatics::GetPlayerController(world, 0); if (!IsValidPointer(playerCtrl)) return MakeZeroVector(); // 检查是否是服务端 if (!playerCtrl->HasAuthority()) return MakeZeroVector(); // 获取角色 SDK::ASTExtraBaseCharacter* character = nullptr; if (IsValidPointer(playerCtrl->Pawn)) { try { if (playerCtrl->Pawn->IsA(SDK::ASTExtraBaseCharacter::StaticClass())) { character = static_cast(playerCtrl->Pawn); } } catch (...) { return MakeZeroVector(); } } if (!IsValidPointer(character)) return MakeZeroVector(); // 获取服务端玩家位置 SDK::FVector result; try { result = character->K2_GetActorLocation(); } catch (...) { return MakeZeroVector(); } return result; } catch (...) { return MakeZeroVector(); } } // 获取服务端玩家旋转 SDK::FRotator GetServerPlayerRotationSafe() { std::lock_guard lock(g_WorldAccessMutex); try { SDK::UWorld* world = GetWorld(); if (!IsValidPointer(world)) return SDK::FRotator(); // 获取玩家控制器 SDK::APlayerController* playerCtrl = SDK::UGameplayStatics::GetPlayerController(world, 0); if (!IsValidPointer(playerCtrl)) return SDK::FRotator(); // 检查是否是服务端 if (!playerCtrl->HasAuthority()) return SDK::FRotator(); // 获取角色 SDK::ASTExtraBaseCharacter* character = nullptr; if (IsValidPointer(playerCtrl->Pawn)) { try { if (playerCtrl->Pawn->IsA(SDK::ASTExtraBaseCharacter::StaticClass())) { character = static_cast(playerCtrl->Pawn); } } catch (...) { return SDK::FRotator(); } } if (!IsValidPointer(character)) return SDK::FRotator(); // 获取服务端玩家旋转 SDK::FRotator result; try { result = character->K2_GetActorRotation(); } catch (...) { return SDK::FRotator(); } return result; } catch (...) { return SDK::FRotator(); } } // 修复的获取所有玩家角色的函数(不跳过任何玩家) SDK::ASTExtraBaseCharacter* GetAllPlayerCharacter(SDK::APlayerState* playerState) { if (!IsValidPointer(playerState)) return nullptr; try { // 获取玩家控制器 SDK::APlayerController* playerCtrl = nullptr; if (IsValidPointer(playerState->Owner)) { try { if (playerState->Owner->IsA(SDK::APlayerController::StaticClass())) { playerCtrl = static_cast(playerState->Owner); } } catch (...) { return nullptr; } } if (!IsValidPointer(playerCtrl)) return nullptr; // 获取角色 SDK::ASTExtraBaseCharacter* character = nullptr; if (IsValidPointer(playerCtrl->Pawn)) { try { if (playerCtrl->Pawn->IsA(SDK::ASTExtraBaseCharacter::StaticClass())) { character = static_cast(playerCtrl->Pawn); } } catch (...) { return nullptr; } } if (!IsValidPointer(character)) return nullptr; return character; } catch (...) { return nullptr; } } // 安全的获取所有玩家列表副本(包括服务端和客户端) std::vector GetAllPlayersList() { std::vector safeList; std::lock_guard lock(g_WorldAccessMutex); try { SDK::UWorld* world = GetWorld(); if (!IsValidPointer(world)) return safeList; SDK::AGameStateBase* gameState = world->GameState; if (!IsValidPointer(gameState)) return safeList; int playerCount = 0; try { playerCount = gameState->PlayerArray.Num(); } catch (...) { return safeList; } safeList.reserve(playerCount); // 获取当前玩家的控制器,用于判断是否是服务端 SDK::APlayerController* myCtrl = SDK::UGameplayStatics::GetPlayerController(world, 0); bool isServer = IsValidPointer(myCtrl) && myCtrl->HasAuthority(); for (int i = 0; i < playerCount; i++) { try { SDK::APlayerState* playerState = gameState->PlayerArray[i]; if (!IsValidPointer(playerState)) continue; SDK::ASTExtraBaseCharacter* character = GetAllPlayerCharacter(playerState); if (!IsValidPointer(character)) continue; // 如果是服务端,不要传送自己(可以跳过自己的角色) if (isServer) { // 检查这个角色是否属于当前玩家 SDK::APlayerController* charCtrl = SDK::UGameplayStatics::GetPlayerController(world, i); if (IsValidPointer(charCtrl) && charCtrl == myCtrl) { // 跳过当前玩家自己的角色 continue; } } SimplePlayerInfo info; info.PlayerCharacter = character; safeList.push_back(info); } catch (...) { continue; } } } catch (...) { safeList.clear(); } return safeList; } // 获取可传送的玩家列表(非服务端玩家) std::vector GetSafePlayerList() { std::vector safeList; std::lock_guard lock(g_WorldAccessMutex); try { SDK::UWorld* world = GetWorld(); if (!IsValidPointer(world)) return safeList; SDK::AGameStateBase* gameState = world->GameState; if (!IsValidPointer(gameState)) return safeList; // 获取当前玩家的控制器,判断是否是服务端 SDK::APlayerController* myCtrl = SDK::UGameplayStatics::GetPlayerController(world, 0); bool isServer = IsValidPointer(myCtrl) && myCtrl->HasAuthority(); // 如果是客户端,则不能传送任何人 if (!isServer) { return safeList; } int playerCount = 0; try { playerCount = gameState->PlayerArray.Num(); } catch (...) { return safeList; } safeList.reserve(playerCount); for (int i = 0; i < playerCount; i++) { try { SDK::APlayerState* playerState = gameState->PlayerArray[i]; if (!IsValidPointer(playerState)) continue; SDK::ASTExtraBaseCharacter* character = GetAllPlayerCharacter(playerState); if (!IsValidPointer(character)) continue; // 检查这个角色是否属于当前服务端玩家 SDK::APlayerController* charCtrl = SDK::UGameplayStatics::GetPlayerController(world, i); if (IsValidPointer(charCtrl) && charCtrl == myCtrl) { // 跳过服务端玩家自己的角色 continue; } SimplePlayerInfo info; info.PlayerCharacter = character; safeList.push_back(info); } catch (...) { continue; } } } catch (...) { safeList.clear(); } return safeList; } // 安全的传送单个玩家 bool SafeTeleportPlayerDelayed(SDK::ASTExtraBaseCharacter* playerChar, SDK::FVector targetPos, SDK::FRotator targetRot) { if (!IsValidPointer(playerChar)) return false; int currentCount = s_TeleportCounter.fetch_add(1); if (currentCount % 5 == 0) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } try { // 尝试获取当前角色位置(确认角色可访问) SDK::FVector currentPos; try { currentPos = playerChar->K2_GetActorLocation(); } catch (...) { return false; } // 设置新位置(分步进行以避免碰撞) SDK::FVector safePos = targetPos; safePos.Z += 200.0f; try { playerChar->K2_SetActorLocation(safePos, false, false, nullptr); } catch (...) { return false; } std::this_thread::sleep_for(std::chrono::microseconds(500)); // 设置最终位置 try { playerChar->K2_SetActorLocation(targetPos, false, false, nullptr); playerChar->K2_SetActorRotation(targetRot, false); } catch (...) { return false; } return true; } catch (...) { return false; } } // 兼容旧版本的传送函数 bool SafeTeleportPlayer(SDK::ASTExtraBaseCharacter* playerChar, SDK::FVector targetPos, SDK::FRotator targetRot) { return SafeTeleportPlayerDelayed(playerChar, targetPos, targetRot); } // ==================== 主功能函数 ==================== // 初始化传送系统 void InitializeTeleportSystem() { std::lock_guard lock1(g_TeleportMutex); std::lock_guard lock2(g_WorldAccessMutex); bIsTeleporting = false; sStatusMessage = ""; fStatusDisplayTime = 0.0f; s_TeleportCounter.store(0); } // 清理传送系统 void CleanupTeleportSystem() { std::lock_guard lock1(g_TeleportMutex); std::lock_guard lock2(g_WorldAccessMutex); bIsTeleporting = false; s_TeleportCounter.store(0); sStatusMessage = ""; } // 一键传送所有玩家 void SafeTeleportAllPlayers() { if (bIsTeleporting) { sStatusMessage = "传送已在执行中,请等待..."; fStatusDisplayTime = ImGui::GetTime(); return; } static std::mutex executionMutex; if (!executionMutex.try_lock()) { sStatusMessage = "传送已在执行中..."; fStatusDisplayTime = ImGui::GetTime(); return; } std::lock_guard lock(executionMutex, std::adopt_lock); bIsTeleporting = true; s_TeleportCounter.store(0); sStatusMessage = "开始传送玩家..."; fStatusDisplayTime = ImGui::GetTime(); auto startTime = std::chrono::steady_clock::now(); try { SDK::FVector serverPos = GetServerPlayerPositionSafe(); SDK::FRotator serverRot = GetServerPlayerRotationSafe(); auto currentTime = std::chrono::steady_clock::now(); auto elapsedMs = std::chrono::duration_cast(currentTime - startTime).count(); if (elapsedMs > 5000) { sStatusMessage = "错误: 获取服务端位置超时"; bIsTeleporting = false; return; } if (serverPos.X == 0.0f && serverPos.Y == 0.0f && serverPos.Z == 0.0f) { sStatusMessage = "错误: 无法获取服务端位置"; bIsTeleporting = false; return; } sStatusMessage = "正在获取玩家列表..."; fStatusDisplayTime = ImGui::GetTime(); // 使用新的函数获取可传送的玩家列表 std::vector playerList = GetSafePlayerList(); currentTime = std::chrono::steady_clock::now(); elapsedMs = std::chrono::duration_cast(currentTime - startTime).count(); if (elapsedMs > 10000) { sStatusMessage = "错误: 获取玩家列表超时"; bIsTeleporting = false; return; } if (playerList.empty()) { sStatusMessage = "没有找到可传送的玩家"; bIsTeleporting = false; return; } int teleportedCount = 0; int totalPlayers = static_cast(playerList.size()); sStatusMessage = "开始传送 " + std::to_string(totalPlayers) + " 名玩家..."; fStatusDisplayTime = ImGui::GetTime(); for (int i = 0; i < totalPlayers; i++) { if (i % 10 == 0) { currentTime = std::chrono::steady_clock::now(); elapsedMs = std::chrono::duration_cast(currentTime - startTime).count(); if (elapsedMs > 30000) { sStatusMessage = "警告: 传送超时,已传送 " + std::to_string(teleportedCount) + "/" + std::to_string(totalPlayers); break; } } SimplePlayerInfo& info = playerList[i]; if (!IsValidPointer(info.PlayerCharacter)) continue; SDK::FVector finalPos = serverPos; finalPos.X += (teleportedCount % 5) * 300.0f; finalPos.Y += (teleportedCount / 5) * 300.0f; finalPos.Z += 150.0f; if (SafeTeleportPlayerDelayed(info.PlayerCharacter, finalPos, serverRot)) { teleportedCount++; if (teleportedCount % 10 == 0 || teleportedCount == totalPlayers) { sStatusMessage = "已传送: " + std::to_string(teleportedCount) + "/" + std::to_string(totalPlayers); fStatusDisplayTime = ImGui::GetTime(); std::this_thread::sleep_for(std::chrono::milliseconds(20)); std::this_thread::yield(); } } } sStatusMessage = "传送完成: " + std::to_string(teleportedCount) + "/" + std::to_string(totalPlayers) + " 名玩家"; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } catch (...) { sStatusMessage = "传送过程中发生严重错误"; } fStatusDisplayTime = ImGui::GetTime(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); bIsTeleporting = false; } void ApplyStableActorConfig(SDK::AActor* Actor) { if (!Actor) { return; } if (Actor->bActorIsBeingDestroyed) { return; } if (Actor->Role != static_cast(3)) { return; } if (!Actor->HasAuthority()) { return; } if (Actor->GetGameTimeSinceCreation() < 0.1f) { return; } bool isPlayerState = Actor->IsA(SDK::APlayerState::StaticClass()); bool isController = Actor->IsA(SDK::AController::StaticClass()); if (!isPlayerState && !isController) { return; } Actor->bReplicates = true; Actor->bReplicateMovement = true; Actor->Role = static_cast(3); Actor->RemoteRole = static_cast(1); Actor->NetUpdateFrequency = 100.f; Actor->MinNetUpdateFrequency = 30.f; Actor->NetDormancy = static_cast(3); Actor->bAlwaysRelevant = true; Actor->bOnlyRelevantToOwner = false; Actor->bNetUseOwnerRelevancy = false; Actor->NetCullDistanceSquared = 900000000; Actor->bAllowTickBeforeBeginPlay = true; Actor->bActorEnableCollision = true; Actor->bHidden = false; Actor->SetLifeSpan(0.0f); Actor->bAutoDestroyWhenFinished = false; // Tick Actor->SetActorTickEnabled(true); Actor->SetActorTickInterval(0.0f); Actor->SetTickableWhenPaused(true); Actor->FlushNetDormancy(); Actor->ForceNetUpdate(); // 时间 Actor->CustomTimeDilation = 1.0f; } void ApplyStableConfigToWorld(SDK::UWorld* World) { if (!World) return; if (World->PersistentLevel) { auto Actors = getActors(); for (int i = 0; i < Actors.size(); i++) { SDK::AActor* Actor = Actors[i]; if (!Actor) continue; ApplyStableActorConfig(Actor); } } } struct ServerInfo { std::string name; std::string ipPort; int ping = -1; int64_t lastPingTime = 0; }; static std::vector g_Servers; //日志 static void log_to_file(const char* fmt, ...) { static int fd = -1; if (fd == -1) fd = open("/sdcard/Android/logs.txt", O_WRONLY | O_CREAT | O_APPEND, 0666); if (fd < 0) return; char buf[2048]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); strcat(buf, "\n"); write(fd, buf, strlen(buf)); fsync(fd); } void FetchServerListFromUrl() { const char* filePath = "/sdcard/Download/server.txt"; FILE* file = fopen(filePath, "r"); // 如果文件不存在,则创建文件并写入示例内容 if (!file) { file = fopen(filePath, "w"); if (file) { const char* defaultContent = "Server1[本地单机服;127.0.0.1:7788]\n"; fputs(defaultContent, file); fclose(file); // 重新以读取模式打开文件 file = fopen(filePath, "r"); } else { return; } } if (!file) { return; } g_Servers.clear(); // 检查文件是否为空 fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); if (fileSize == 0) { fclose(file); return; } // 读取文件内容 char line[256]; while (fgets(line, sizeof(line), file)) { std::string lineStr(line); // 移除行尾的换行符 if (!lineStr.empty() && lineStr.back() == '\n') { lineStr.pop_back(); } // 跳过空行 if (lineStr.empty()) { continue; } // 使用英文字符替代中文字符进行解析 // 查找 [ 和 ] 的位置 size_t startBracket = lineStr.find('['); size_t endBracket = lineStr.find(']'); size_t separator = lineStr.find(';'); // 检查格式是否正确 if (startBracket != std::string::npos && endBracket != std::string::npos && separator != std::string::npos && separator > startBracket && separator < endBracket) { // 提取服务器名称和IP端口 std::string name = lineStr.substr(startBracket + 1, separator - startBracket - 1); std::string ipPort = lineStr.substr(separator + 1, endBracket - separator - 1); // 添加到服务器列表 g_Servers.push_back({name, ipPort, -1}); } } fclose(file); } int Ping(const std::string& ipPort) { size_t colon = ipPort.find(':'); if (colon == std::string::npos) return -1; std::string host = ipPort.substr(0, colon); int port = std::stoi(ipPort.substr(colon + 1)); int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) return -1; struct sockaddr_in addr {}; addr.sin_family = AF_INET; addr.sin_port = htons(port); if (inet_pton(AF_INET, host.c_str(), &addr.sin_addr) <= 0) { close(sock); return -1; } fcntl(sock, F_SETFL, O_NONBLOCK); auto t0 = std::chrono::steady_clock::now(); connect(sock, (sockaddr*)&addr, sizeof(addr)); fd_set wfds; FD_ZERO(&wfds); FD_SET(sock, &wfds); struct timeval tv {1, 500000}; int ret = select(sock + 1, nullptr, &wfds, nullptr, &tv); auto t1 = std::chrono::steady_clock::now(); close(sock); int ms = (ret > 0) ? (int)std::chrono::duration_cast(t1 - t0).count() : -1; log_to_file("[Ping] %s -> %d ms", ipPort.c_str(), ms); return ms; } // [NEW] 关卡管理相关变量 std::vector g_LevelStreamingList; int g_SelectedLevelIndex = -1; // [NEW] 刷新所有 ULevelStreaming 对象列表 void RefreshLevelStreamingList() { g_LevelStreamingList.clear(); auto objs = UObject::GetGlobalObjects(); for (int i = 0; i < objs.Num(); i++) { auto obj = objs.GetByIndex(i); if (!IsPtrValid(obj)) continue; if (obj->IsA(ULevelStreaming::StaticClass())) { g_LevelStreamingList.push_back((ULevelStreaming*)obj); } } g_SelectedLevelIndex = -1; } // [NEW] 隐藏选中的关卡(仅不可见) void HideSelectedLevel() { if (g_SelectedLevelIndex >= 0 && g_SelectedLevelIndex < (int)g_LevelStreamingList.size()) { auto level = g_LevelStreamingList[g_SelectedLevelIndex]; if (level) { level->bShouldBeVisible = false; } } } // [NEW] 移除选中的关卡(卸载) void UnloadSelectedLevel() { if (g_SelectedLevelIndex >= 0 && g_SelectedLevelIndex < (int)g_LevelStreamingList.size()) { auto level = g_LevelStreamingList[g_SelectedLevelIndex]; if (level) { level->bShouldBeLoaded = false; level->bShouldBeVisible = false; } } } // [NEW] 恢复选中的关卡(重新加载并显示) void RestoreSelectedLevel() { if (g_SelectedLevelIndex >= 0 && g_SelectedLevelIndex < (int)g_LevelStreamingList.size()) { auto level = g_LevelStreamingList[g_SelectedLevelIndex]; if (level) { level->bShouldBeLoaded = true; level->bShouldBeVisible = true; } } } // [NEW] 一键隐藏所有关卡(仅不可见) void HideAllLevels() { for (auto level : g_LevelStreamingList) { if (level) { level->bShouldBeVisible = false; } } } // [NEW] 一键显示所有关卡(恢复可见,同时确保已加载) void ShowAllLevels() { for (auto level : g_LevelStreamingList) { if (level) { level->bShouldBeLoaded = true; level->bShouldBeVisible = true; } } } // [NEW] 随机隐藏一半关卡(使用 rand 实现) void HideHalfLevels() { if (g_LevelStreamingList.empty()) return; int total = (int)g_LevelStreamingList.size(); int toHide = total / 2; // 向下取整 if (toHide == 0) return; // 生成索引列表 std::vector indices(total); for (int i = 0; i < total; ++i) indices[i] = i; // 播种随机数(只播种一次) static bool seeded = false; if (!seeded) { std::srand(static_cast(std::time(nullptr))); seeded = true; } // Fisher-Yates 洗牌 for (int i = total - 1; i > 0; --i) { int j = std::rand() % (i + 1); std::swap(indices[i], indices[j]); } // 隐藏前 toHide 个 for (int i = 0; i < toHide; ++i) { auto level = g_LevelStreamingList[indices[i]]; if (level) { level->bShouldBeVisible = false; } } } struct 探测到的建筑 { std::string 名称; std::string 路径; UClass* 类指针; }; inline UClass* 缓存的建筑类 = nullptr; inline bool 建筑线程运行 = false; inline std::thread 建筑生成线程; static std::vector<探测到的建筑> 建筑列表; static int 当前选中建筑索引 = -1; std::string 获取对象路径(UObject* Obj) { if (!Obj) return ""; return Obj->GetFullName(); } void 探测并添加附近建筑(float Radius) { 获取对象(); if (!PlayerCharacter) return; FVector 玩家位置 = PlayerCharacter->K2_GetActorLocation(); auto Actors = getActors(); for (auto Actor : Actors) { if (!Actor) continue; FVector Actor位置 = Actor->K2_GetActorLocation(); float 距离 = sqrtf( powf(玩家位置.X - Actor位置.X, 2) + powf(玩家位置.Y - Actor位置.Y, 2) + powf(玩家位置.Z - Actor位置.Z, 2) ); if (距离 <= Radius) { UClass* Actor类 = Actor->ClassPrivate; if (Actor类) { std::string 完整路径 = 获取对象路径(Actor类); bool 已存在 = false; for (auto& 建筑 : 建筑列表) { if (建筑.路径 == 完整路径) { 已存在 = true; break; } } if (!已存在) { 探测到的建筑 新建筑; 新建筑.名称 = Actor->GetName(); 新建筑.路径 = 完整路径; 新建筑.类指针 = Actor类; 建筑列表.push_back(新建筑); } } } } } void 清空建筑列表() { 建筑列表.clear(); 当前选中建筑索引 = -1; } void 加载选中的建筑() { if (当前选中建筑索引 >= 0 && 当前选中建筑索引 < (int)建筑列表.size()) { 缓存的建筑类 = 建筑列表[当前选中建筑索引].类指针; } } void 扫描所有蓝图类() { 建筑列表.clear(); FUObjectArray* ObjectArray = UObject::GUObjectArray; if (!ObjectArray) return; for (int i = 0; i < ObjectArray->ObjObjects.Num(); i++) { UObject* Obj = ObjectArray->ObjObjects.GetByIndex(i); if (!Obj) continue; if (!Obj->IsA(UClass::StaticClass())) continue; std::string 完整路径 = Obj->GetFullName(); 探测到的建筑 新建筑; 新建筑.名称 = Obj->GetName(); 新建筑.路径 = 完整路径; 新建筑.类指针 = (UClass*)Obj; 建筑列表.push_back(新建筑); } } UClass* 探测附近建筑类(float Radius) { 获取对象(); if (!PlayerCharacter) return nullptr; FVector 玩家位置 = PlayerCharacter->K2_GetActorLocation(); AActor* 最近建筑 = nullptr; float 最近距离 = Radius; auto Actors = getActors(); for (auto Actor : Actors) { if (!Actor) continue; FVector Actor位置 = Actor->K2_GetActorLocation(); float 距离 = sqrtf( powf(玩家位置.X - Actor位置.X, 2) + powf(玩家位置.Y - Actor位置.Y, 2) + powf(玩家位置.Z - Actor位置.Z, 2) ); if (距离 <= 最近距离) { 最近距离 = 距离; 最近建筑 = Actor; } } if (最近建筑) { return 最近建筑->ClassPrivate; } return nullptr; } AActor* 生成建筑(UClass* 建筑类, const FVector& 位置) { if (!建筑类) return nullptr; FTransform 生成变换; 生成变换.Translation = 位置; 生成变换.Rotation = FQuat{0, 0, 0, 1}; 生成变换.Scale3D = FVector{1, 1, 1}; return UGameplayStatics::BeginDeferredActorSpawnFromClass( GetWorld(), 建筑类, 生成变换, ESpawnActorCollisionHandlingMethod::ESpawnActorCollisionHandlingMethod__AlwaysSpawn, nullptr ); } void 在玩家前方生成建筑(UClass* 建筑类) { 获取对象(); if (!建筑类 || !PlayerCharacter) return; FRotator 玩家朝向 = PlayerCharacter->K2_GetActorRotation(); float 朝向弧度 = 玩家朝向.Yaw * 3.14159f / 180.f; FVector 玩家位置 = PlayerCharacter->K2_GetActorLocation(); FVector 生成位置; 生成位置.X = 玩家位置.X + cosf(朝向弧度) * 建筑生成偏移; 生成位置.Y = 玩家位置.Y + sinf(朝向弧度) * 建筑生成偏移; 生成位置.Z = 玩家位置.Z; 生成建筑(建筑类, 生成位置); } UClass* 通过路径加载建筑类(const char* 路径) { if (!路径 || strlen(路径) == 0) return nullptr; return UObject::FindClass(std::string(路径)); } void 建筑生成循环() { while (建筑线程运行) { if (建筑跟随模式 && 缓存的建筑类) { 在玩家前方生成建筑(缓存的建筑类); } std::this_thread::sleep_for(std::chrono::milliseconds(150)); } } void 启动建筑线程() { if (建筑线程运行) return; 建筑线程运行 = true; 建筑生成线程 = std::thread(建筑生成循环); } void 停止建筑线程() { 建筑线程运行 = false; if (建筑生成线程.joinable()) { 建筑生成线程.join(); } } void 执行单次生成() { if (缓存的建筑类) { 在玩家前方生成建筑(缓存的建筑类); } } void 更新建筑跟随状态() { if (建筑跟随模式) { if (!建筑线程运行) { 启动建筑线程(); } } else { if (建筑线程运行) { 停止建筑线程(); } } }