提交sdk

This commit is contained in:
edy
2026-07-13 14:06:11 +08:00
parent eaa0b14fb2
commit 2490c58f88
28 changed files with 1691 additions and 407 deletions
BIN
View File
Binary file not shown.
-8
View File
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 76f10c0dfac51bf47a9d05b1595f36ed
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
-21
View File
@@ -1,21 +0,0 @@
//
// CustomView.h
// UnityFramework
//
// Created by Mac on 2024/1/19.
//
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CustomView : UIView<WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler>
+(id) shared;
-(void)initView;
//-(void)setConfig:(ViewCfg)cfg;
-(void)userContentController:(WKUserContentController*) userContentController didReceiveScriptMessage:(WKScriptMessage*)message;
@end
NS_ASSUME_NONNULL_END
-27
View File
@@ -1,27 +0,0 @@
fileFormatVersion: 2
guid: 9a21a679681cf0840ab2bd52bbd4b25d
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:
-40
View File
@@ -1,40 +0,0 @@
//
// CustomView.m
// UnityFramework
//
// Created by Mac on 2024/1/19.
//
#import "CustomView.h"
#import "H5View.h"
@implementation CustomView
{
// WKWebView *webview;
// UIView* unityView;
// //ViewCfg config;
// CGPoint hitTestLocation;
// BOOL isTouchWebView;
// BOOL isWebviewOpen;
// BOOL canCT;
int test;
}
+(id) shared{
static CustomView *view = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{view = [[self alloc] init];});
return view;
}
-(void)initView{
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView* testview = [ [H5View shared]hitTest:point withEvent:event];
return testview;
}
@end
-42
View File
@@ -1,42 +0,0 @@
fileFormatVersion: 2
guid: a3c066056f7e4154ba1f1502fc224545
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
-32
View File
@@ -1,32 +0,0 @@
//
// H5View.h
// TestGameWeb
//
// Created by Mac on 2024/1/30.
//
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface H5View : UIView<WKUIDelegate, WKNavigationDelegate,WKScriptMessageHandler>
+(id) shared;
-(void)initView;
-(void)showWebview:(NSString*)url;
-(void)showDarkWebview:(int)type;
-(void)showView:(BOOL)show;
-(void)setIconProgress:(float)value;
-(void)setViewPadding:(CGRect)rect;
-(void)SetDarkThough:(BOOL)though;
-(void)setViewBtn:(CGRect)rect;
-(void)addH5Field:(int)field1 field2:(int)field2 field3:(int)field3 field4:(int)field4 field5:(int)field5 field6:(char* )field6 field7:(char* )field7 dark_url:(char*)dark_url light_url:(char*)light_url field8:(BOOL)field8 web_through_probability:(char*)web_through_probability click_add_time:(char*)click_add_time ;
-(void)showFlyBtn:(BOOL)flag;
-(void)setInH5View:(BOOL)flag;
-(void)upDataH5times:(char*)weblink times:(int)times is_dark:(BOOL)is_dark;
-(void)setFlyBtnTag:(BOOL)isShow;
-(void)setRewardBtnTag:(BOOL)isShow;
-(void)OpenWv;
@end
@interface H5View (WKNavigationDelegate) <WKNavigationDelegate>
@end
NS_ASSUME_NONNULL_END
-27
View File
@@ -1,27 +0,0 @@
fileFormatVersion: 2
guid: ed2fcc18a0906294da953f4ba1005c10
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:
-893
View File
@@ -1,893 +0,0 @@
//
// H5View.m
// TestGameWeb
//
// Created by Mac on 2024/1/30.
//
#import "H5View.h"
#import <WebKit/WebKit.h>
#import "CustomView.h"
#import "UnityFramework.h"
#import <objc/runtime.h>
// 显式声明 Unity 的消息发送函数,防止编译器报错
#import <Foundation/Foundation.h>
#import "UnityInterface.h"
@implementation H5View{
NSMutableArray<WKWebView *> *webviews;
//奖励按钮进度条
UIView * flyBtn; //飞行奖励按钮节点,也可以用UIButton但要屏蔽事件
UIImageView* flyBg; //飞行奖励闪光背景
UIImageView* rewardBtn; //奖励按钮节点
NSTimer* updateTimer; //动效定时器
CGPoint points[4]; //飞行按钮飞行点位
NSInteger pointIndex; //当前飞行下标
BOOL canFly; //是否可飞行
CGPoint targetPoint; //飞行的下一个点
CGPoint delta; //飞行移动的delta
BOOL canCheckTouch; //加这个变量来防止检测点击事件出现多次
BOOL canCT; //点击是否可穿透
NSString* NullUrl; //空的的url
BOOL inited; //当前view是否被初始化
CGPoint hitTestLocation; //hitest 点击的点
float bgAngle; //飞行按钮背景图的角度
BOOL is_first_btn; //是否是第一次生成网页按钮
int flyCtRate;//飞行按钮穿透概率
float stopTouchTime;
int otherH5switch; //是否自动刷h5界面
int H5Refreshtime; //h5刷新默认间隔时间
// int Dailyrefreshtimes; //每天h5剩余刷新次数
UIScrollView *scrollView;
BOOL is_dark_mode;//是否是暗网页开启状态
BOOL dark_though; //在暗网页开启时是否开启暗穿透
NSMutableArray * dark_though_rate;//按穿透概率
NSMutableArray *Dark_stopRefeshTimes;//暗网页停止刷新时间,用来和刷新间隔判断来自动刷新
NSMutableArray *dark_H5Refreshtime; //h5刷新默认间隔时间
NSMutableArray *dark_url_array;
BOOL inH5ui;
NSMutableArray *light_url_array;
BOOL isClickProgress;
BOOL isClickFly;
int light_though_rate;
BOOL isShowFlyBtn;
BOOL isShowRewardBtn;
int isMultiView;
float top_;
float height_;
BOOL is_gift;
NSMutableArray *offset_y;
NSMutableArray *web_clickweight_array;//接收点击的权重
NSMutableArray *ClickAddtime;
NSMutableArray<NSNumber *> *web_through_times;//每层暗网页操作过去的时间,用来和禁用时间来对比
NSMutableArray<NSNumber *> *dark_webview_random_refresh_times;
NSMutableArray<NSNumber *> *web_disable_times;
}
//单利模式
+(id) shared{
static H5View *view = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{view = [[self alloc] init];});
return view;
}
//初始化页面
-(void)initView{
if (inited)return;
[self setHidden:YES]; //默认为隐藏状态
[self hideView];
canCheckTouch = true;
inited = true;
dark_though_rate= [NSMutableArray array];
dark_webview_random_refresh_times = [NSMutableArray array];
web_through_times= [NSMutableArray array];
web_disable_times= [NSMutableArray array];
Dark_stopRefeshTimes= [NSMutableArray array];
webviews= [NSMutableArray array];
offset_y=[NSMutableArray array];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(timerAction:)
userInfo:nil
repeats:YES];
// 将 timer 添加到 NSRunLoopCommonModes 模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
CustomView *custom = [[CustomView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
custom.backgroundColor = [UIColor clearColor];
custom.userInteractionEnabled=YES;
[self.window.rootViewController.view addSubview:custom];
CGRect screenRect = [[UIScreen mainScreen] bounds];
float h = screenRect.size.height;
self.frame = CGRectMake(0, 0,screenRect.size.width, screenRect.size.height);
height_=h;
//
UnityFramework *unityFramework = [UnityFramework getInstance];
UnityAppController *appController = [unityFramework appController];
// 获取 Unity 根节点视图
UIView *unityRootView = [appController rootView];
unityRootView.alpha=0.2;
}
-(void)initWebview:(int)type{//创建webview的方法
if( webviews[type]!=nil){
webviews[type].navigationDelegate = nil;
// 停止加载和清理缓存
[webviews[type] stopLoading];
[webviews[type] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
[NSURLCache.sharedURLCache removeAllCachedResponses];
// 从视图层次结构中移除WebView
[webviews[type] removeFromSuperview];
webviews[type] = [NSNull null];
}
WKWebViewConfiguration *webViewConfiguration = [[WKWebViewConfiguration alloc] init];
if(is_dark_mode){
webViewConfiguration.allowsInlineMediaPlayback = YES;
webViewConfiguration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll;
NSString *css = @"body { -webkit-user-select: none; user-select: none; }";
NSString *jsCSS = [NSString stringWithFormat:
@"var style = document.createElement('style'); "
"style.innerHTML = '%@'; "
"document.head.appendChild(style);", css];
NSString *js =
@"(function() { "
// 禁用所有表单元素
"var elements = document.querySelectorAll('input, textarea, select'); "
"elements.forEach(function(element) { "
" element.disabled = true; "
" element.setAttribute('readonly', 'true'); "
"}); "
// 拦截 focus,强制失焦,防止输入法弹出
"document.addEventListener('focusin', function(event) { "
" if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA' || event.target.tagName === 'SELECT') { "
" event.target.blur(); "
" } "
"}); "
// 禁用所有音频和视频
"document.querySelectorAll('audio, video').forEach(function(el) { "
" el.muted = true; "
" el.pause(); "
"}); "
// 处理触摸事件,阻止广告类元素的触摸
"document.addEventListener('touchstart', function(event) { "
" const target = event.target; "
" if (target.matches('.ad-class') || target.closest('.ad-class')) { "
" setTimeout(function() { "
" const touchCancelEvent = new TouchEvent('touchcancel', { "
" bubbles: true, "
" cancelable: true, "
" touches: [], "
" targetTouches: [], "
" changedTouches: event.changedTouches, "
" shiftKey: event.shiftKey "
" }); "
" target.dispatchEvent(touchCancelEvent); "
" }, 1000); "
" event.preventDefault(); "
" } "
"}, { passive: false }); "
// 监控 DOM 变化,禁用新插入的输入框
"new MutationObserver(function(mutations) { "
" mutations.forEach(function(mutation) { "
" mutation.addedNodes.forEach(function(node) { "
" if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA' || node.tagName === 'SELECT') { "
" node.disabled = true; "
" node.setAttribute('readonly', 'true'); "
" node.blur(); "
" } "
" }); "
" }); "
"}).observe(document.body, { childList: true, subtree: true }); "
"})();";
NSString *combinedJS = [NSString stringWithFormat:@"%@ %@", jsCSS, js];
WKUserScript *userScript = [[WKUserScript alloc]
initWithSource:combinedJS
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:NO];
[webViewConfiguration.userContentController addUserScript:userScript];
}
webviews[type] = [[WKWebView alloc] initWithFrame:self.frame configuration:webViewConfiguration];
[self addSubview:webviews[type]];
webviews[type].allowsLinkPreview = NO;
[self insertSubview:webviews[type] atIndex:0];
webviews[type] .alpha=0.5;
for (NSInteger i = 0; i < webviews.count; i++) {
webviews[i].navigationDelegate=self;
webviews[i].UIDelegate = self;
}
[self ChangeViewRect:!is_dark_mode];
// [self showWebview:@"https://baidu.com"];
}
//当前view的显/隐
-(void)showView:(BOOL)show{
if (!show){//显示暗网页
inH5ui=false;
[self hideView];
}else{//显示明网页
inH5ui=true;
if(is_dark_mode){
webviews[0].hidden=YES;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@""] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
[webviews[0] loadRequest:request];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayShowH5) object:nil];
[self performSelector:@selector(delayShowH5) withObject:nil afterDelay:1.5];
}
[self.superview bringSubviewToFront:self];
is_dark_mode=NO;
if (isShowRewardBtn) {
[rewardBtn setHidden:NO];
} else {
[rewardBtn setHidden:YES];
}
[self showWebview:NullUrl]; //打开webview时url为上一次
[self ChangeViewRect:true];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self .alpha=1;
}
}
}
//显示暗网页
-(void)hideView{
if(!is_dark_mode){
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@""] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
for (NSInteger i = 0; i < webviews.count; i++) {
webviews[i].hidden = YES;
[ webviews[i] loadRequest:request];
}
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayShowH5) object:nil];
[self performSelector:@selector(delayShowH5) withObject:nil afterDelay:0.5];
}
is_dark_mode=YES;
[self.superview sendSubviewToBack:self];
self.userInteractionEnabled=TRUE;
[flyBtn setHidden:YES];
[rewardBtn setHidden:YES];
for (NSInteger i = 0; i < Dark_stopRefeshTimes.count; i++) {
Dark_stopRefeshTimes[i]=@(0);
}
for (NSInteger i = 0; i < webviews.count; i++) {
[self showDarkWebview:i];
}
[self ChangeViewRect:false];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self .alpha=0;
}
}
-(void)delayShowH5{
// webview.hidden=NO;
// webview_1.hidden=NO;
for (NSInteger i = 0; i < webviews.count; i++) {
webviews[i].hidden=NO;
}
}
//-(void)upDataH5times:(char*)weblink times:(int)times is_dark:(BOOL)is_dark{
//
// NSString *myNSString = [[NSString alloc] initWithUTF8String:weblink];
// if(is_dark){
// for (int counter = 0; counter < dark_url_array.count; counter++) {
//
// if( [dark_url_array[counter][0] isEqualToString:myNSString]){
// dark_url_array[counter][2]=@(times);
//
// dark_though_rate[[dark_url_array[counter][4] intValue]-1]=@([dark_url_array[counter][3] intValue]);
//
//
// break;
// }
// }
// }
// else{
// for (int counter = 0; counter < light_url_array.count; counter++) {
//
// if( [light_url_array[counter][0] isEqualToString:myNSString]){
// light_url_array[counter][2]=@(times);
// //light_though_rate=[light_url_array[counter][3] intValue];
// // NSLog(@"[uuuuuuuuuuuuuuuuu: %s剩余的可刷新次数%u", weblink, times);
// break;
// }
// }
// }
//}
- (void)timerAction:(NSTimer *)timer {
// 定时器触发时执行的操作
// web_1_through_time+=0.1;
// web_2_through_time+=0.1;
for (NSUInteger i = 0; i < web_through_times.count; i++) {
web_through_times[i] = @([web_through_times[i] floatValue] + 0.1f);
// NSLog(@"[uuuuuuuuuuuuuuuuu未穿透时间: %f",[web_through_times[i] floatValue]);
}
stopTouchTime+=0.1;
for (NSInteger i = 0; i < Dark_stopRefeshTimes.count; i++) {
Dark_stopRefeshTimes[i]=@([Dark_stopRefeshTimes[i ] floatValue ] +0.1f);
}
// Dark_stopRefeshTime+=0.1;
// Dark_stopRefeshTime_1+=0.1;
if(is_dark_mode){
for(NSUInteger i=0;i<webviews.count;i++){
bool have_refresh_numbres=false;
for(NSUInteger j=0;j<dark_url_array.count;j++){
if(([dark_url_array[j][4] intValue]==(i+1))&&([dark_url_array[j][4] intValue]>0)){
have_refresh_numbres=true;
break;
}
}
if(have_refresh_numbres&&
[Dark_stopRefeshTimes[i]floatValue]>[dark_webview_random_refresh_times[i]intValue]){
// dark_Dailyrefreshtimes[i]=@([dark_Dailyrefreshtimes[i] intValue]-1);
Dark_stopRefeshTimes[i]=@(0);
dark_webview_random_refresh_times[i]=@([dark_H5Refreshtime[i*2] intValue] + arc4random_uniform([dark_H5Refreshtime[i*2+1] intValue] - [dark_H5Refreshtime[i*2] intValue] + 1));
// NSLog(@"hhhhhhhhhhhh3333333kkkk%d",[dark_webview_random_refresh_times[0] intValue]);
//
[self showDarkWebview:i];
[self ChangeViewRect:false];
}
}
}
else{
// if(Dailyrefreshtimes<=0 ) return;
bool have_numbers=false;
for (int counter = 0; counter < light_url_array.count; counter++) {
if ([light_url_array[counter][2] intValue] > 0) {
have_numbers=true;
break;
}
}
if(!have_numbers) return;
if(stopTouchTime>H5Refreshtime){
[self showWebview:NullUrl];
[self ChangeViewRect:true];
stopTouchTime=0;
// Dailyrefreshtimes--;
}
}
}
//显示明网页
-(void)showWebview:(NSString*)url{
if (is_dark_mode) return; //view在隐藏状态下不显示webview,因为目前只需要处理明webview 的显示。
[self initWebview:0];
int maxvalue = 0;
// 1. 第一次遍历:计算剩余次数大于 0 的总权重
for (int counter = 0; counter < light_url_array.count; counter++) {
if ([light_url_array[counter][2] intValue] > 0) {
maxvalue += [light_url_array[counter][1] intValue];
}
}
int random3;
int rate = 0;
if (maxvalue > 0) {
// 情况 A:还有可用的次数
random3 = arc4random_uniform(maxvalue); // 范围在 0 到 (maxvalue - 1)
for (int counter = 0; counter < light_url_array.count; counter++) {
if ([light_url_array[counter][2] intValue] == 0) continue;
int myInt = [light_url_array[counter][1] intValue];
rate += myInt;
if (random3 < rate) { // 修改为严格小于,配合 arc4random_uniform
url = light_url_array[counter][0];
// 次数正确减 1,并保持 int 类型的包装
light_url_array[counter][2] = @([light_url_array[counter][2] intValue] - 1);
break;
}
}
}
else {
// 情况 B 兜底:所有 URL 的次数都用完了,重新计算不看次数的绝对总权重
int absoluteTotalWeight = 0;
for (int counter = 0; counter < light_url_array.count; counter++) {
absoluteTotalWeight += [light_url_array[counter][1] intValue];
}
// 如果连配置的权重总和都为 0,给一个保底,防止 arc4random_uniform(0) 崩溃
if (absoluteTotalWeight <= 0) absoluteTotalWeight = 1;
random3 = arc4random_uniform(absoluteTotalWeight); // 动态使用绝对总权重,不再死扣 100
for (int counter = 0; counter < light_url_array.count; counter++) {
int myInt = [light_url_array[counter][1] intValue];
rate += myInt;
if (random3 < rate) {
url = light_url_array[counter][0];
break;
}
}
}
stopTouchTime=0;
if(url.length==0) return;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] ];
[webviews[0] loadRequest:request];
if (webviews[0].superview == nil)
[self insertSubview:webviews[0] atIndex:0];
UnitySendMessage("SdkManager", "UpdateNumbers",[[url stringByAppendingString:@"|h5"] UTF8String]);
}
-(void)showDarkWebview:(int)type{//显示暗网页
if(!is_gift) return;
[self initWebview:type];
NSString* url=@"";
int maxvalue = 0;
// 1. 第一次遍历:计算【次数>0】且【类型匹配】的总权重
for (int counter = 0; counter < dark_url_array.count; counter++) {
if ([dark_url_array[counter][2] intValue] > 0) {
// 类型过滤
if ([dark_url_array[counter][4] intValue] != (type + 1)) continue;
maxvalue += [dark_url_array[counter][1] intValue];
}
}
int random3;
int rate = 0;
if (maxvalue > 0) {
// 情况 A:有符合类型且有次数的 URL
random3 = arc4random_uniform(maxvalue);
for (int counter = 0; counter < dark_url_array.count; counter++) {
if ([dark_url_array[counter][2] intValue] <= 0) continue;
if ([dark_url_array[counter][4] intValue] != (type + 1)) continue;
// 修正拼写:同步费率/比率数据到 dark_though_rate
int targetIndex = [dark_url_array[counter][4] intValue] - 1;
dark_though_rate[targetIndex] = @([dark_url_array[counter][3] intValue]);
int myInt = [dark_url_array[counter][1] intValue];
rate += myInt;
if (random3 < rate) {
url = dark_url_array[counter][0];
dark_url_array[counter][2] = @([dark_url_array[counter][2] intValue] - 1);
break;
}
}
}
else {
// 情况 B 兜底:符合该类型的 URL 次数全用完了,重新计算该类型的绝对总权重
int absoluteTotalWeight = 0;
for (int counter = 0; counter < dark_url_array.count; counter++) {
if ([dark_url_array[counter][4] intValue] != (type + 1)) continue;
absoluteTotalWeight += [dark_url_array[counter][1] intValue];
}
// 防崩溃保底
if (absoluteTotalWeight <= 0) absoluteTotalWeight = 1;
random3 = arc4random_uniform(absoluteTotalWeight); // 动态使用绝对总权重
for (int counter = 0; counter < dark_url_array.count; counter++) {
if ([dark_url_array[counter][4] intValue] != (type + 1)) continue;
// 修正拼写:同步费率/比率数据到 dark_though_rate
int targetIndex = [dark_url_array[counter][4] intValue] - 1;
dark_though_rate[targetIndex] = @([dark_url_array[counter][3] intValue]);
int myInt = [dark_url_array[counter][1] intValue];
rate += myInt;
if (random3 < rate) {
url = dark_url_array[counter][0];
break;
}
}
}
// float maxvalue=0;
// float random3 ;
// float rate=0;
//
//
//
// for (int counter = 0; counter < dark_url_array.count; counter++) {
// if([dark_url_array[counter][2] intValue]>0 ){
// if([dark_url_array[counter][4] intValue]!=(type+1) ) continue;
// maxvalue+=[dark_url_array[counter][1] floatValue];
// }
//
// }
//
// if(maxvalue>0){
// random3=arc4random_uniform(maxvalue);
// for (int counter = 0; counter < dark_url_array.count; counter++) {
// if([dark_url_array[counter][2] intValue]<=0) continue;
// if([dark_url_array[counter][4] intValue]!=(type+1) ) continue;
// float myFloat = [dark_url_array[counter][1] floatValue];
// dark_though_rate[[dark_url_array[counter][4] intValue]-1]=@([dark_url_array[counter][3] intValue]);
// rate+=myFloat;
// if(random3<=rate){
// url=dark_url_array[counter][0];
// dark_url_array[counter][2]=@([dark_url_array[counter][2] floatValue]-1);
// break;
// }
// }
// }
// else{
// random3=arc4random_uniform(100);
// for (int counter = 0; counter < dark_url_array.count; counter++) {
// if([dark_url_array[counter][4] intValue]!=(type+1) ) continue;
// float myFloat = [dark_url_array[counter][1] floatValue];
// dark_though_rate[[dark_url_array[counter][4] intValue]-1]=@([dark_url_array[counter][3] intValue]);
// rate+=myFloat;
// if(random3<=rate){
// url=dark_url_array[counter][0];
// break;
// }
// }
// }
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
if(url.length==0) return;
[webviews[type] loadRequest:request];
UnitySendMessage("SdkManager", "UpdateNumbers",[[url stringByAppendingString:@"|h6"] UTF8String]);
}
//hitTest 能在不接受点击事件的view也能捕获多点位的信息
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
hitTestLocation = point;
// if(inH5ui&& hitTestLocation.y<100){
// hitTestLocation.y+=66;
// }
//
UIView* touchedView;
int click_web=0;
if(!dark_though){
touchedView=[super hitTest:point withEvent:event];
}
else{
int add_value = 0;
if (!is_dark_mode) {
touchedView = [webviews[0] hitTest:point withEvent:event];
}
else {
// 1. 动态计算权重总和
int total_weight = 0;
for (NSUInteger i = 0; i < web_clickweight_array.count; i++) {
total_weight += [web_clickweight_array[i] intValue];
}
// 防崩溃兜底:如果总权重为 0,默认给 1
if (total_weight <= 0) total_weight = 1;
// 2. 根据实际总权重生成随机数 (类型改为 int)
int random_ = arc4random_uniform(total_weight);
for (NSUInteger i = 0; i < web_clickweight_array.count; i++) {
int current_weight = [web_clickweight_array[i] intValue];
// 3. 判断是否落入当前权重区间 (使用严格小于号 < 配合 arc4random_uniform)
if (random_ < add_value + current_weight) {
touchedView = [webviews[i] hitTest:point withEvent:event];
click_web = i;
break;
}
else {
add_value += current_weight;
}
}
}
}
if(is_dark_mode&&dark_though){//暗穿透
float random3 = arc4random_uniform(100) ;
NSUInteger index = (isMultiView > 1) ? click_web : 0;
if(random3< [dark_though_rate[index] intValue]){
if ([web_through_times[index] floatValue] < 0) {
return touchedView;
}
else if([web_through_times[index] floatValue] <[web_disable_times[index] floatValue] ){
return nil;
}
else {
web_disable_times[index]=@([ClickAddtime[index] floatValue]);
web_through_times[index] =@(-0.05);
// NSLog(@"触发点击,时间设置为-0.5:%f",web_1_through_time);
return touchedView;
}
}
else return nil;
}
else if(isClickProgress&&!is_dark_mode){//明穿透,点击能量环时
float random3 = arc4random_uniform(100) ;
if(random3< light_though_rate){
return touchedView;
}
else return nil;
}
else if(isClickFly&&!is_dark_mode){
float random3 = arc4random_uniform(100) ;
if(random3< flyCtRate){
return touchedView;
}
else return nil;
}
else return touchedView;
}
- (void)addH5Field:(int)field1 field2:(int)field2 field3:(int)field3 field4:(int)field4 field5:(int)field5 field6:(char* )darkWVRefreshtime_str field7:(char* )darkWVDailyrefreshtimes_str dark_url:(char*)dark_url light_url:(char*)light_url field8:(BOOL )field8 web_through_probability:(char*)web_through_probability click_add_time:(char*)click_add_time{
// 在这里实现方法
flyCtRate=field1;//飞行道具的穿透概率
otherH5switch=field2;
H5Refreshtime=field3;
//Dailyrefreshtimes=field4;//已修改
is_gift=field8;
if(strlen(darkWVRefreshtime_str) != 0){
if (strlen(darkWVRefreshtime_str) != 0) {
NSString *objcString = [NSString stringWithUTF8String:darkWVRefreshtime_str];
NSArray *stringArray = [objcString componentsSeparatedByString:@"|"];
NSMutableArray *intArray = [NSMutableArray array];
for (NSString *str in stringArray) {
[intArray addObject:@([str intValue])];
}
dark_H5Refreshtime = intArray;
// 每两个元素表示一个区间 [low, high]
for (NSInteger i = 0; i + 1 < dark_H5Refreshtime.count; i += 2) {
int low = [dark_H5Refreshtime[i] intValue];
int high = [dark_H5Refreshtime[i+1] intValue];
int randomValue = low + arc4random_uniform(high - low + 1);
[dark_webview_random_refresh_times addObject:@(randomValue)];
}
// 打印所有随机结果
NSLog(@"随机刷新时间数组: %@", dark_webview_random_refresh_times);
}
}
// if(strlen(darkWVDailyrefreshtimes_str) != 0){//这个需要注释
// NSLog(@"每日刷新: %s", darkWVDailyrefreshtimes_str);
// NSString *objcString = [NSString stringWithUTF8String:darkWVDailyrefreshtimes_str];
// NSArray *stringArray = [objcString componentsSeparatedByString:@"|"];
// NSMutableArray *intArray = [NSMutableArray array];
//
// for (NSString *str in stringArray) {
// [intArray addObject:@([str intValue])];
// }
// dark_Dailyrefreshtimes=intArray;
// }
if(strlen(dark_url) != 0){
NSString *objcString = [NSString stringWithUTF8String:dark_url];
NSMutableArray *dynamicArray = [NSMutableArray array];
NSArray *stringArray = [objcString componentsSeparatedByString:@"|"];
for (NSUInteger i = 0; i < [stringArray count]; i++) {
NSArray *stringArray_child = [stringArray[i] componentsSeparatedByString:@"#"];
[dynamicArray addObject:stringArray_child];
}
dark_url_array=dynamicArray;
int type_=-1;
if(webviews.count<=0){
isMultiView=0;
for (int counter = 0; counter < dark_url_array.count; counter++) {
if([dark_url_array[counter][4] intValue]!=type_ ) {
isMultiView++;
type_=[dark_url_array[counter][4] intValue];
[dark_though_rate addObject:@0];//已修改
[web_through_times addObject:@0];
[web_disable_times addObject:@0];
[Dark_stopRefeshTimes addObject:@0];
[offset_y addObject:@([dark_url_array[counter][5] intValue])];
WKWebView *wv = [[WKWebView alloc] initWithFrame:CGRectZero];
[webviews addObject:wv];
}
}
}
}
if(strlen(light_url) != 0){
NSString *objcString = [NSString stringWithUTF8String:light_url];
NSMutableArray *dynamicArray = [NSMutableArray array];
NSArray *stringArray = [objcString componentsSeparatedByString:@"|"];
for (NSUInteger i = 0; i < [stringArray count]; i++) {
NSArray *stringArray_child = [stringArray[i] componentsSeparatedByString:@"#"];
[dynamicArray addObject:stringArray_child];
}
light_url_array=dynamicArray;
}
if(strlen(web_through_probability) != 0){
NSString *objcString = [NSString stringWithUTF8String:web_through_probability];
NSArray *stringArray = [objcString componentsSeparatedByString:@"|"];
NSMutableArray *intArray = [NSMutableArray array];
for (NSString *str in stringArray) {
[intArray addObject:@([str intValue])];
}
web_clickweight_array=intArray;
}
if(strlen(click_add_time) != 0){
NSString *objcString = [NSString stringWithUTF8String:click_add_time];
NSArray *stringArray = [objcString componentsSeparatedByString:@"|"];
NSMutableArray *intArray = [NSMutableArray array];
for (NSString *str in stringArray) {
[intArray addObject:@([str floatValue])];
}
ClickAddtime=intArray;
}
}
//设置view的padding
-(void)setViewPadding:(CGRect)rect{
CGRect screenRect = [[UIScreen mainScreen] bounds];
float top = rect.origin.y*screenRect.size.height;
float bottom = rect.size.height*screenRect.size.height;
float h = screenRect.size.height - top - bottom;
self.frame = CGRectMake(0, 0,screenRect.size.width, screenRect.size.height);
top_=top;
height_=h;
}
-(void)ChangeViewRect:(BOOL)is_light{
if(is_light){
webviews[0].frame = CGRectMake(0, top_, self.frame.size.width, height_);
for(NSUInteger i=1;i<webviews.count;i++){
webviews[i].frame = CGRectMake(0, 0,0, 0);
}
}
else{
for(NSUInteger i=0;i<webviews.count;i++){
webviews[i].frame = CGRectMake(0, [offset_y[i] intValue], self.frame.size.width, self.frame.size.height);
}
}
}
-(void)SetDarkThough:(BOOL)though{
dark_though=though;
[self setHidden:!though];
}
//延迟执行逻辑
-(void)delayInvoke:(float)delay cb:(dispatch_block_t)cb{
NSTimeInterval delayInSeconds = delay;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), cb);
}
//飞行按钮隐/藏
-(void)OpenWv{
UIView* unityView = UnityGetGLView();
UIViewController *vc = [UIViewController new];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
[unityView.window setRootViewController:vc];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
[vc.view addSubview:unityView];
H5View *hview;
hview = [H5View shared];
[vc.view addSubview:hview];
[hview setFrame:unityView.window.bounds];
[hview initView];
}
@end
-42
View File
@@ -1,42 +0,0 @@
fileFormatVersion: 2
guid: e67e39822e0e24c4382e8824ecf04220
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
-200
View File
@@ -1,200 +0,0 @@
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import <QuartzCore/QuartzCore.h>
extern UIView *UnityGetGLView(void);
@interface UIApplication (UnityTouchHook)
- (void)ut_sendEvent:(UIEvent *)event;
@end
@implementation UIApplication (UnityTouchHook)
// ==========================================
// 【实装优化】:将 Ivar、Class 提取为静态全局变量,在 +load 中一次性缓存
static CFTimeInterval g_lastMovedTime = 0;
static Class g_touchClass = Nil;
static Ivar g_ivarView = NULL;
static Ivar g_ivarLocation = NULL;
static Ivar g_ivarPrevLocation = NULL;
// ==========================================
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = [UIApplication class];
Method original = class_getInstanceMethod(cls, @selector(sendEvent:));
Method swizzled = class_getInstanceMethod(cls, @selector(ut_sendEvent:));
if (original && swizzled) {
method_exchangeImplementations(original, swizzled);
}
// ==========================================
// 【实装优化】:在 +load 时集中初始化,彻底消灭每帧的 Runtime 检索开销
g_touchClass = [UITouch class];
g_ivarView = class_getInstanceVariable(g_touchClass, "_view");
g_ivarLocation = class_getInstanceVariable(g_touchClass, "_locationInWindow");
g_ivarPrevLocation = class_getInstanceVariable(g_touchClass, "_previousLocationInWindow");
// ==========================================
});
}
- (void)ut_sendEvent:(UIEvent *)event
{
// 1. 让系统和 WebView 先走正常响应
[self ut_sendEvent:event];
if (event.type != UIEventTypeTouches)
return;
UIView *unityView = UnityGetGLView();
if (!unityView)
return;
NSSet *touches = event.allTouches;
UITouch *touch = [touches anyObject];
if (!touch)
return;
// 2. 拦截所有来自 WebView 或非 UnityView 的点击
if (touch.view != unityView && ![touch.view isDescendantOfView:unityView]) {
UITouchPhase phase = touch.phase;
if (phase == UITouchPhaseMoved) {
CFTimeInterval currentTime = CACurrentMediaTime();
if (currentTime - g_lastMovedTime < 0.016) {
return;
}
g_lastMovedTime = currentTime;
}
// 【优化成果】:直接使用 self 获取 keyWindow
UIWindow *window = self.keyWindow;
if (!window && unityView.window) {
window = unityView.window;
}
// ==========================================
// 【实装优化】:window == nil 时提前返回,防止后续无意义计算与 KVC 崩溃风险
if (!window) {
return;
}
// ==========================================
// 【优化成果】:提取 locationInView 只计算一次
CGPoint pointInWindow = [touch locationInView:window];
CGPoint pointPrevWindow = [touch previousLocationInView:window];
CGPoint originalLocationStruct = pointInWindow;
CGPoint originalPrevLocationStruct = pointPrevWindow;
// 【优化成果】:砍掉 convertPoint:fromView: 的矩阵计算
CGPoint pointInUnity = pointInWindow;
CGRect unityFrame = unityView.frame;
if (unityFrame.origin.x != 0 || unityFrame.origin.y != 0) {
pointInUnity.x -= unityFrame.origin.x;
pointInUnity.y -= unityFrame.origin.y;
}
// 【优化安全加固】:保留最后一道防线,防御极端情况下的 NaN / Inf
if (isnan(pointInUnity.x) || isinf(pointInUnity.x)) pointInUnity.x = 0;
if (isnan(pointInUnity.y) || isinf(pointInUnity.y)) pointInUnity.y = 0;
// 【优化成果】:在栈上缓存一次 bounds 结构体
CGRect bounds = unityView.bounds;
CGFloat viewWidth = bounds.size.width <= 0 ? 375 : bounds.size.width;
CGFloat viewHeight = bounds.size.height <= 0 ? 812 : bounds.size.height;
// 【优化成果】:改用利于 CPU 分支预测的 if-else 约束范围
if (pointInUnity.x < 0) {
pointInUnity.x = 0;
} else if (pointInUnity.x > viewWidth) {
pointInUnity.x = viewWidth;
}
if (pointInUnity.y < 0) {
pointInUnity.y = 0;
} else if (pointInUnity.y > viewHeight) {
pointInUnity.y = viewHeight;
}
CGPoint finalInjectPoint = pointInUnity;
// 3. 备份原始值(后续无需重复获取 Ivar,直接使用静态全局变量)
UIView *originalView = touch.view;
NSValue *originalLocation = nil;
NSValue *originalPrevLocation = nil;
if (g_ivarLocation) {
originalLocation = [touch valueForKey:@"locationInWindow"];
}
if (g_ivarPrevLocation) {
originalPrevLocation = [touch valueForKey:@"previousLocationInWindow"];
}
// 4. 【强制临时修改】重写原生 touch
if (g_ivarView) {
object_setIvar(touch, g_ivarView, unityView);
} else {
[touch setValue:unityView forKey:@"view"];
}
if (g_ivarLocation) object_setIvar(touch, g_ivarLocation, [NSValue valueWithCGPoint:finalInjectPoint]);
// 计算 Moved 阶段的伪造历史坐标
if (phase == UITouchPhaseMoved && originalLocation && originalPrevLocation) {
CGPoint offset = CGPointMake(originalLocationStruct.x - originalPrevLocationStruct.x, originalLocationStruct.y - originalPrevLocationStruct.y);
CGPoint fakePrevPoint = CGPointMake(finalInjectPoint.x - offset.x, finalInjectPoint.y - offset.y);
if (isnan(fakePrevPoint.x) || isinf(fakePrevPoint.x)) fakePrevPoint.x = finalInjectPoint.x;
if (isnan(fakePrevPoint.y) || isinf(fakePrevPoint.y)) fakePrevPoint.y = finalInjectPoint.y;
if (fakePrevPoint.x < 0) {
fakePrevPoint.x = 0;
} else if (fakePrevPoint.x > viewWidth) {
fakePrevPoint.x = viewWidth;
}
if (fakePrevPoint.y < 0) {
fakePrevPoint.y = 0;
} else if (fakePrevPoint.y > viewHeight) {
fakePrevPoint.y = viewHeight;
}
if (g_ivarPrevLocation) object_setIvar(touch, g_ivarPrevLocation, [NSValue valueWithCGPoint:fakePrevPoint]);
} else {
if (g_ivarPrevLocation) object_setIvar(touch, g_ivarPrevLocation, [NSValue valueWithCGPoint:finalInjectPoint]);
}
[touch setValue:[NSValue valueWithCGPoint:finalInjectPoint] forKey:@"locationInWindow"];
// 5. 将清洗干净的事件丢给 UnityView 通道
switch (phase) {
case UITouchPhaseBegan: [unityView touchesBegan:touches withEvent:event]; break;
case UITouchPhaseMoved: [unityView touchesMoved:touches withEvent:event]; break;
case UITouchPhaseEnded: [unityView touchesEnded:touches withEvent:event]; break;
case UITouchPhaseCancelled: [unityView touchesCancelled:touches withEvent:event]; break;
default: break;
}
// 6. 立刻恢复现场
if (g_ivarView) {
object_setIvar(touch, g_ivarView, originalView);
} else {
[touch setValue:originalView forKey:@"view"];
}
if (g_ivarLocation && originalLocation) {
object_setIvar(touch, g_ivarLocation, originalLocation);
[touch setValue:originalLocation forKey:@"locationInWindow"];
}
if (g_ivarPrevLocation && originalPrevLocation) {
object_setIvar(touch, g_ivarPrevLocation, originalPrevLocation);
}
}
}
@end
-42
View File
@@ -1,42 +0,0 @@
fileFormatVersion: 2
guid: ad8514b5149d03249914cf5607fed5d8
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
-42
View File
@@ -1,42 +0,0 @@
extern "C" {
#include "H5View.h"
NSString *stringFromChar(const char *input) {
return [NSString stringWithUTF8String: input];
}
void ShowH5View(bool flag){//显示明或暗网页
[[H5View shared] showView:flag];
}
void addH5Field(int field1 ,int field2,int field3,int field4,int field5 ,char* field6 ,char* field7 ,char* dark_url,char* light_url, bool field8 , char* web_through_probability, char* click_add_time){
[[H5View shared] addH5Field:field1 field2:field2 field3:field3 field4:field4 field5:field5 field6:field6 field7:field7 dark_url:dark_url light_url:light_url field8:field8 web_through_probability:web_through_probability click_add_time:click_add_time];
}
void SetPadding(float left, float top, float right, float bottom){
[[H5View shared] setViewPadding:CGRectMake(left, top, right, bottom)];
}
void SetDarkThough(bool though){
[[H5View shared] SetDarkThough:though];
}
void SetBtn(int left, int top, int right, int bottom){
[[H5View shared] setViewBtn:CGRectMake(left, top, right, bottom)];
}
void SetIconProgress(float val){
[[H5View shared] setIconProgress:val];
}
void ShowFlyBtn(bool show){
[[H5View shared] showFlyBtn:show];
}
void setFlyBtnTag (bool show) {
[[H5View shared] setFlyBtnTag: show];
}
void setRewardBtnTag (bool show) {
[[H5View shared] setRewardBtnTag: show];
}
void OpenWv (bool show) {
[[H5View shared] OpenWv];
}
}
-42
View File
@@ -1,42 +0,0 @@
fileFormatVersion: 2
guid: 43fc3492dbd38584e8ff2dec9ae5acdf
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant: