1
0
forked from gcdsfh/PMDT
Files
PMDT/variables.h
T
2026-05-03 14:19:19 +08:00

3564 lines
118 KiB
C++
Executable File

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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<APickUpWrapperActor*>(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<std::string> 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<std::string>& out) {
std::lock_guard<std::mutex> lk(log_mutex);
out = logs;
}
private:
int local_port;
std::string target_ip;
int target_port;
int sockfd;
std::atomic<bool> running;
std::thread worker;
std::mutex log_mutex;
std::vector<std::string> logs;
std::mutex clients_mutex;
std::map<std::pair<std::string,int>, 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<milliseconds>(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<std::mutex> 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<std::mutex> lk(clients_mutex);
client_timestamps[{ipbuf, port}] =
std::chrono::duration_cast<std::chrono::milliseconds>(
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<double, std::milli>(t1 - t0).count();
push_packet_log("客户端->服务端", delay, len, ipbuf, port, to_hex(buf, len));
} else {
std::pair<std::string,int> latest;
bool found = false;
{
std::lock_guard<std::mutex> 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<double, std::milli>(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<std::string>& out) {
if (g_proxy) g_proxy->get_logs(out);
}
///===========抓包结束=========///
inline void push_log(const string &s) {
std::lock_guard<std::mutex> 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<uint8_t> 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<uint8_t> 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<uint8_t>(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<milliseconds>(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<bool> running; // 改为 atomic
int sockfd;
sockaddr_in client_address;
std::thread worker; // 添加线程成员
// 响应数据存储
std::vector<std::vector<uint8_t>> 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<std::string, std::string> 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<std::string> 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<uint8_t> get_response_for_client(const std::vector<uint8_t>& 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<uint8_t> 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<uint8_t>& 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<uint8_t>& 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<std::chrono::milliseconds>(
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<std::string>& out_lines) {
std::lock_guard<std::mutex> lk(g_log_mutex);
out_lines = g_log_lines;
}
// ==== Original main.cpp content follows ====
// ====================================================
// 车辆修复专用日志系统 - 独立于现有日志系统
// ====================================================
namespace VehicleFixLog {
static std::vector<std::string> LogEntries;
static std::mutex LogMutex;
static const int MAX_LOG_ENTRIES = 500;
// 添加日志
void AddLog(const std::string& message) {
std::lock_guard<std::mutex> 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<std::mutex> lock(LogMutex);
LogEntries.clear();
}
// 获取日志副本
std::vector<std::string> GetLogs() {
std::lock_guard<std::mutex> lock(LogMutex);
return LogEntries;
}
// 获取最近N条日志
std::vector<std::string> GetRecentLogs(int count) {
std::lock_guard<std::mutex> lock(LogMutex);
if (LogEntries.size() <= count) {
return LogEntries;
}
return std::vector<std::string>(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<PlayerInfo> RegisteredPlayers;
// 状态跟踪
std::map<SDK::APlayerController*, int> LastSeatIndices;
std::map<SDK::APlayerController*, SDK::ASTExtraVehicleBase*> LastVehicles;
std::map<SDK::APlayerController*, bool> 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<float>(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 <mutex>
#include <atomic>
#include <vector>
#include <thread>
#include <chrono>
#include <string>
#include <cstdlib>
// ==================== 玩家信息结构体 ====================
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<int> s_TeleportCounter(0);
// ==================== 辅助函数 ====================
// 创建零向量
SDK::FVector MakeZeroVector() {
SDK::FVector vec;
vec.X = 0.0f;
vec.Y = 0.0f;
vec.Z = 0.0f;
return vec;
}
// 改进的指针有效性检查
template<typename T>
bool IsValidPointer(T* ptr) {
if (!ptr) return false;
// 检查指针是否指向有效地址范围(简化版)
uintptr_t addr = reinterpret_cast<uintptr_t>(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<std::mutex> 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<SDK::ASTExtraBaseCharacter*>(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<std::mutex> 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<SDK::ASTExtraBaseCharacter*>(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<SDK::APlayerController*>(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<SDK::ASTExtraBaseCharacter*>(playerCtrl->Pawn);
}
} catch (...) {
return nullptr;
}
}
if (!IsValidPointer(character)) return nullptr;
return character;
} catch (...) {
return nullptr;
}
}
// 安全的获取所有玩家列表副本(包括服务端和客户端)
std::vector<SimplePlayerInfo> GetAllPlayersList() {
std::vector<SimplePlayerInfo> safeList;
std::lock_guard<std::mutex> 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<SimplePlayerInfo> GetSafePlayerList() {
std::vector<SimplePlayerInfo> safeList;
std::lock_guard<std::mutex> 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<std::mutex> lock1(g_TeleportMutex);
std::lock_guard<std::mutex> lock2(g_WorldAccessMutex);
bIsTeleporting = false;
sStatusMessage = "";
fStatusDisplayTime = 0.0f;
s_TeleportCounter.store(0);
}
// 清理传送系统
void CleanupTeleportSystem() {
std::lock_guard<std::mutex> lock1(g_TeleportMutex);
std::lock_guard<std::mutex> 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<std::mutex> 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<std::chrono::milliseconds>(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<SimplePlayerInfo> playerList = GetSafePlayerList();
currentTime = std::chrono::steady_clock::now();
elapsedMs = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime).count();
if (elapsedMs > 10000) {
sStatusMessage = "错误: 获取玩家列表超时";
bIsTeleporting = false;
return;
}
if (playerList.empty()) {
sStatusMessage = "没有找到可传送的玩家";
bIsTeleporting = false;
return;
}
int teleportedCount = 0;
int totalPlayers = static_cast<int>(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<std::chrono::milliseconds>(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<SDK::ENetRole>(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<SDK::ENetRole>(3);
Actor->RemoteRole = static_cast<SDK::ENetRole>(1);
Actor->NetUpdateFrequency = 100.f;
Actor->MinNetUpdateFrequency = 30.f;
Actor->NetDormancy = static_cast<SDK::ENetDormancy>(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<ServerInfo> 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<std::chrono::milliseconds>(t1 - t0).count() : -1;
log_to_file("[Ping] %s -> %d ms", ipPort.c_str(), ms);
return ms;
}
// [NEW] 关卡管理相关变量
std::vector<ULevelStreaming*> 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<int> indices(total);
for (int i = 0; i < total; ++i) indices[i] = i;
// 播种随机数(只播种一次)
static bool seeded = false;
if (!seeded) {
std::srand(static_cast<unsigned>(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 (线)
{
线();
}
}
}