查看: 22|回复: 22

86JP S4A21版本服务端开发日记

 火... [复制链接]

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
发表于 昨天 03:03 | 显示全部楼层 |阅读模式
断断续续也开发了80多天,留个帖子记录一下开发相关的内容。
exe的sha-256:1F8244D3F7309BBE2FDE4299E1863A894F6B28D5707BF01732980585B20B00DD

        🔒 您需要登录才可以查看图片,请 登录注册
   
阿荣社区欢迎你(bbs.vul7.com)
回复

使用道具 举报

发表于 昨天 03:04 | 显示全部楼层
大佬牛逼
阿荣社区欢迎你(bbs.vul7.com)
回复

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:04 | 显示全部楼层
首先要知道的是DNF的服务器和客户端通信是用的两种协议类型一种是CMD,另一种是NOTI。CMD顾名思义就是命令协议。一般是客户端向服务端请求CMD,然后服务端返回响应CMD和若干NOTI。
NOTI是通知类型的协议,如背包栏内容变化,城镇人物变化等都是由NOTI来实现的。比如开箱子的协议就是典型的CMD和NOTI共同协作完成的业务功能。比如开启服务端买的60个魔盒的那个盒子。流程就是如下:
卡恩的命运回响礼盒:10007368
普通幸运魔锤:10007367
一、客户端发起开盒请求
======================
批量开启使用:
方向:Client -> Server
帧族:CMD 0x01
Type:0x0450
用途:批量开启魔盒
请求Body固定为15字节:
u8 客户端列表类型
i16 箱子所在槽位
i32 客户端所见箱子ID
i16 材料所在槽位,-1表示未指定
i32 客户端所见材料ID
u16 本次开启数量
卡恩礼盒的真实请求样例:
00 4200 48B39800 7A00 47B39800 3C00
解析结果:
列表类型 = 0
箱子槽位 = 66
箱子ID = 10007368
魔锤槽位 = 122
魔锤ID = 10007367
开启数量 = 60
单个开启还可使用CMD 0x00D0。它的Body只有列表类型、箱子槽位和材料槽位,
开启数量固定为1,实际物品ID由服务端从当前角色背包读取。
二、业务流程
1. 解析请求
服务端确认协议类型、Body长度、槽位格式、物品ID和开启数量是否合法。
格式错误直接返回失败,不进入物品结算。
2. 确认当前角色和背包状态
服务端确认当前连接已经选择角色,并从该角色的服务端背包读取箱子槽位。
客户端提交的箱子ID只是校验值,不能替代服务端背包中的真实数据。
3. 查询PVF开盒规则
服务端使用背包中真实的箱子ID查询PVF,取得:
- 该物品是否属于可开启魔盒;
- 每次开启需要消耗多少个箱子;
- 是否需要钥匙或其他材料;
- 每次要抽取哪些奖励池;
- 奖励物品ID、数量和权重;
- 是否存在期限、装扮属性、宠物或其他特殊奖励规则。
4. 校验请求与PVF是否一致
服务端将客户端提交的箱子槽位、箱子ID、材料槽位、材料ID和开启数量,
与当前背包和PVF要求进行比对。
如果箱子不存在、数量不足、魔锤不匹配、材料不足、物品已过期,
或请求试图绕过PVF材料要求,则整次开启失败。
5. 根据PVF计算奖励
服务端按照PVF定义独立计算每次开启的奖励。
客户端不能指定奖励物品或奖励数量。
批量开启时,服务端重复执行指定次数的奖励计算,最后汇总同类奖励,
同时保留开盒结果窗口需要的奖励展示信息。
6. 预先规划完整结算
在修改数据库之前,服务端先确认:
- 要扣除的箱子和材料仍然存在;
- 所有奖励都是服务端支持创建的物品;
- 奖励没有失效或过期;
- 可以合并到哪些已有堆叠;
- 需要占用哪些新槽位;
- 背包、装扮栏或宠物栏是否有足够空间。
只要任意奖励无法完整发放,整个请求都失败,不扣箱子和材料。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:05 | 显示全部楼层
7.在一个事务中持久化
服务端把以下变化作为一个整体写入数据库:
-扣除箱子;
-扣除魔锤或其他材料;
-增加全部奖励物品;
-写入新物品实例及其期限、属性等信息;
-如果该箱子使用幸运值,同时更新账户幸运值;
-如果包含期限权益或宠物,同时更新对应持久化记录。
事务全部成功后才视为开盒成功;任何一步失败都整体回滚。
8.数据库提交后通知客户端
成功结算后的发送顺序为:
第一帧:S->CCMD0x0450
这是批量魔盒的成功应答,也是驱动客户端原生开盒结果窗口的协议。
回包中包含成功标志、开启数量、箱子槽位、材料槽位、奖励条目,
以及普通奖励列表和幸运奖励列表。
客户端据此关闭或刷新开盒操作窗口,并在原生结果窗口中显示
本次获得的物品和数量。
后续帧:S->CNOTI0x000EUPDATE_ITEM_LIST
该通知携带变更后槽位的绝对状态,用于刷新客户端背包UI。
奖励进入或合并到的槽位会发送最新物品和数量;
箱子或材料被用完的槽位会发送空槽状态;
尚有剩余数量的槽位会发送扣除后的绝对数量。
如果奖励包含期限权益、宠物等非普通背包内容,再追加相应的专项通知。
必须先发送CMD0x0450,再发送NOTI0x000E。
原因是客户端处理魔盒成功应答时会先在本地扣除箱子和材料,
随后的绝对背包状态用于把客户端UI校正为服务端数据库中的最终结果。
9.失败处理
失败时仍使用S->CCMD0x0450返回:
007E背包空间不足
0016材料不足
0002其他拒绝
失败回包不包含奖励列表,不发送背包更新通知,数据库也不产生物品变化。
三、卡恩礼盒60连开示例
1.客户端发送CMD0x0450:
箱子槽位66,物品10007368,数量60
魔锤槽位122,物品10007367
2.服务端读取PVF后得到:
每开启1次消耗:
卡恩的命运回响礼盒10007368x1
普通幸运魔锤10007367x1
每开启1次获得:
瞬间移动药剂2600014x2
赛丽亚魔盒2682272x1
3.服务端计算60次结果:
消耗:
10007368x60
10007367x60
获得:
2600014x120
2682272x60
4.服务端先把扣除和奖励作为一个事务持久化到数据库。
5.数据库提交成功后,服务端发送:
CMD0x0450
让客户端确认开盒成功,并在原生开盒结果窗口中显示:
瞬间移动药剂x120
赛丽亚魔盒x60
NOTI0x000EUPDATE_ITEM_LIST
把奖励所在槽位、箱子槽位和魔锤槽位的最终绝对状态发给客户端,
让背包UI与服务端数据库保持一致。
四、流程摘要
客户端发送CMD0x0450
->服务端解析箱子槽位、材料槽位和开启数量
->从服务端背包确认真实物品
->查询PVF取得材料要求和奖励规则
->校验材料、数量、期限和背包空间
->服务端计算奖励
->在一个事务中扣除箱子/材料并写入奖励
->数据库提交成功
->返回CMD0x0450显示原生开盒结果窗口
->发送NOTI0x000E刷新背包槽位和数量
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:05 | 显示全部楼层
也就是说对于客户端来说,UI显示获取了哪些东西都只是障眼法。实际的获取是靠更新LISTITEM来完成消耗品栏多出来瞬移药剂和赛利亚礼盒。这个设计模式也贯穿了全部的DNF实际操作流程。所以理论上你在本地啥都不干,只靠服务端发NOTI就能完成装备栏凭空多装备这种操作。因为很多NOTI协议并不限定接收时机,你什么时候发就什么时候处理。完全没有合法性校验。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:06 | 显示全部楼层
先写这些垫个底,后续等组队协议都完成了,再完整解析整个组队流程和同步过程。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:07 | 显示全部楼层
然后,接下来是城镇协议模型。这决定了你在这个区域能看到谁,以及谁能看到你。还有就是赛利亚旅店为什么是每个人一个区域的原因。本身客户端并没有强制要求赛利亚旅店里看不到别人。这部分完全是由服务端来决定的。所以只要你无视了pvf里的相应字段,完全可以一堆人挤在赛利亚宾馆里大眼瞪小眼。
以下是协议的详细解析:
城镇人物同步不是“广播一条人物出现协议”,而是一个完整的可见性生命周期:
建立远端人物对象
-> 下发人物可见性
-> 下发人物所在区域和坐标
-> 下发当前区域权威名册
-> 持续同步移动
-> 换区时重建新旧区域的可见性
-> 真正退出时销毁人物对象
赛丽亚旅馆也不应通过给每个玩家伪造不同的城镇ID或区域ID实现。
正确思路是:PVF中的区域编号保持不变,但区域模型决定它是共享空间还是每角色私有空间。
二、城镇人物同步涉及的主要协议
1. S -> C NOTI 0x0002 USERINFO,subtype 0
用途:在客户端创建或补齐一个远端角色的公开人物对象。
主要包含:
- 网络角色ID;
- 角色身份和名称;
- 职业、等级等公开状态;
- 装备与外观;
- 宠物等公开展示信息。
只发送位置或区域名册,不足以让客户端创建一个从未见过的远端角色。
因此,远端角色第一次进入接收者视野时,必须先发送本协议。
2. S -> C NOTI 0x0165 CHARAC_INVISIBLE_FALGS
用途:同步该角色的可见性状态位。
Body核心内容:
u16 角色网络ID
u8 可见性状态位
它决定客户端是否以及如何绘制已经建立的人物对象。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:07 | 显示全部楼层
3.S->CNOTI0x0017USER_AREA
用途:告诉客户端某个角色当前位于哪个城镇区域和哪个坐标。
Body为10字节:
u16角色网络ID
u8城镇ID
u8区域ID
i16X坐标
i16Y坐标
u8朝向
u8区域状态
它负责“这个人物位于哪里”,但不负责创建人物对象,也不代表完整区域成员关系。
4.S->CNOTI0x0018AREA_USERS
用途:发送一个城镇区域的完整权威名册。
Body结构:
u8城镇ID
u8区域ID
u16名册人数
对每名角色重复:
u16角色网络ID
i16X坐标
i16Y坐标
u8朝向
u8区域状态
该协议不是只有多人时才发送。
单人区域仍然发送count=1并包含本人,否则客户端可能无法完成换区状态切换。
多人时,每个接收者收到的名册都应把自己放在第一条,后面再列同区域其他角色。
5.C->SCMD0x0023SET_USER_POSITION
用途:客户端上报角色在当前区域内的移动位置。
A21已知Body为7字节:
i16X坐标
i16Y坐标
u8朝向
u16移动状态尾部
6.S->CNOTI0x0016USER_POSITION
用途:确认并广播角色在当前区域内的位置变化。
A21已知Body为9字节:
u16角色网络ID
i16X坐标
i16Y坐标
u8朝向
u16移动状态尾部
服务端向上报者回送一份,同时向当前可见范围内的其他玩家广播。
7.C->SCMD0x0024SET_USER_AREA
用途:客户端走到区域边界后,请求进入另一个城镇区域。
当前协议中可确认的主要字段:
u8目标城镇ID
u8目标区域ID
i16目标X坐标
i16目标Y坐标
u8朝向
其余为区域切换上下文字段
成功路径不是简单回一条同类型CMD,而是通过NOTI0x0017和NOTI0x0018完成换区。
8.S->CNOTI0x0006USER_LEAVE
用途:销毁客户端持有的该角色对象。
Body核心内容:
u16离开的角色网络ID
它只适合角色真正退出当前世界,例如正常退出、返回选角、会话替换或断线清理。
普通城镇换区不应使用它,否则可能连带销毁客户端上的队员和P2P状态。
三、进入城镇区域时的人物同步流程
1.服务端得到当前角色的城镇、区域、坐标、朝向和公开外观。
2.服务端从区域模型读取该角色对当前接收者是否可见,以及当前区域的权威成员集合。
3.对于接收者此前没有建立过的每个远端角色,依次发送:
NOTI0x0002subtype0
创建远端角色的公开人物对象
NOTI0x0165
设置远端角色的可见性状态
NOTI0x0017
把远端角色放入正确的城镇、区域和坐标
4.所有需要建立的远端角色都准备好以后,发送:
NOTI0x0018AREA_USERS
该帧给出接收者当前应看到的完整区域名册,并把接收者本人放在第一条。
5.对区域内原有玩家执行对称流程:
-给原有玩家发送新进入者的0x0002、0x0165和0x0017;
-再向每个原有玩家发送以其本人开头的0x0018完整名册。
因此,同区人物出现的最小协议顺序是:
0x0002subtype0
->0x0165
->0x0017
->0x0018
其中0x0002创建人物,0x0017放置人物,0x0018确认区域成员关系。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:08 | 显示全部楼层
四、区域内移动同步流程
1.客户端发送CMD0x0023,上报位置、朝向和移动状态。
2.服务端确认该角色仍属于当前会话和当前区域。
3.服务端更新区域模型中的最新位置。
4.服务端向上报者返回NOTI0x0016,确认服务器采用的位置。
5.如果当前区域是共享区域,则向该区域其他可见玩家广播同一条NOTI0x0016。
6.如果当前区域是私人赛丽亚旅馆,则接收者集合只有本人,不向其他会话广播。
移动协议只更新已经存在的人物对象;如果接收端还没有该人物对象,必须先完成上一节的
0x0002、0x0165、0x0017、0x0018人物建立流程。
五、城镇换区同步流程
1.客户端发送CMD0x0024,声明目标城镇、区域和落点。
2.服务端查询PVF,确认:
-目标城镇和区域确实存在;
-当前频道允许进入该城镇;
-目标区域属于共享区域还是私人区域;
-目标位置和区域上下文可以接受。
3.服务端把角色从旧区域成员集合迁移到新区域成员集合。
4.向迁移者发送:
NOTI0x0017
确认新的城镇、区域和落点
对新区域中尚未建立的其他角色发送:
NOTI0x0002subtype0
NOTI0x0165
NOTI0x0017
NOTI0x0018
发送迁移者在新区域看到的完整权威名册
5.向新区域原有玩家发送:
新迁入角色的0x0002、0x0165、0x0017
以及各自个性化的0x0018完整名册
6.向旧区域剩余玩家发送:
NOTI0x0018
这份旧区域权威名册不再包含迁移者,客户端据此移除旧区域中的人物投影。
7.普通换区不发送NOTI0x0006。
换区的本质不是“销毁角色再创建角色”,而是同一个在线角色从一个区域投影转移到另一个区域投影。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:08 | 显示全部楼层
六、赛丽亚旅馆成为私人空间的机制
PVF城镇定义会给区域标注用途:
[gate]
角色进入城镇时的赛丽亚到达房间
[normal]
普通共享城镇区域
[dungeongate]
通往地下城的共享区域
当前A21内容和实机结果表明:
[gate]=每角色私有的赛丽亚旅馆空间
[normal]=同频道、同城镇、同区域玩家共享
[dungeongate]=同频道、同城镇、同区域玩家共享
关键点是:两个玩家可以拥有完全相同的townId和areaId,但仍然不属于同一个可见空间。
建议把区域的有效可见空间建模为:
共享区域:
channelId+townId+areaId
私人赛丽亚区域:
channelId+townId+areaId+ownerCharacterId
也可以不直接暴露这个组合键,而使用等价的可见性规则:
如果区域类型是[gate]:
一个玩家只能看见自己
如果区域类型是[normal]或[dungeongate]:
玩家可以看见同频道、同城镇、同区域的全部共享成员
私人赛丽亚旅馆中的协议表现为:
1.每个玩家仍收到自己的NOTI0x0017。
2.每个玩家仍收到NOTI0x0018,但名册是:
count=1
唯一成员=自己
3.不向另一个私人旅馆玩家发送对方的:
NOTI0x0002subtype0
NOTI0x0165
NOTI0x0017
NOTI0x0016
NOTI0x0018成员信息
4.两个玩家即使townId和areaId完全相同,也不会互相出现、互相收到移动或区域成员变化。
5.当玩家从[gate]走入[normal]时,才加入共享区域名册,并触发远端人物建立与完整名册同步。
6.当玩家从[normal]返回[gate]时:
-共享区域剩余玩家收到不含该玩家的0x0018;
-返回者收到只包含自己的0x0018;
-不需要为私人房间制造新的城镇ID或区域ID。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:09 | 显示全部楼层
七、重点建议:对区域进行响应式建模
不要让登录、选角、移动、换区、地下城返回、断线和会话替换各自决定要向谁发送哪些协议。
这种“每个业务点手工推送”的方式会快速产生大量独立通知点位,并容易出现:
-新增一种进入路径却忘记发送0x0002;
-换区只更新新区域,没有清理旧区域名册;
-私人赛丽亚房间把移动错误广播给同编号的其他玩家;
-断线与普通换区都使用0x0006,误删队伍或P2P状态;
-不同入口产生不同协议顺序;
-延迟事件把旧区域状态重新覆盖到客户端。
更合适的模型是维护一个权威区域状态:
AreaState
区域标识:channelId、townId、areaId
区域类型:private-per-character或shared
私人空间拥有者:仅私人区域需要
当前成员集合
每个成员的公开人物快照
每个成员的坐标、朝向和区域状态
当前区域版本号
所有业务入口只更新事实:
角色进入区域
角色移动
角色换区
角色退出世界
角色公开外观或可见性变化
区域模型随后为每个受影响的接收者计算:
DesiredView(viewer)
=viewer在当前区域按可见性规则应该看到的角色集合
再把DesiredView与该接收者上一次已投影视图进行差分:
新增角色
->0x0002subtype0
->0x0165
->0x0017
区域成员集合变化
->0x0018完整权威名册
已存在角色移动
->0x0016
角色普通跨区而不再可见
->旧区域0x0018中删除
角色真正退出世界
->0x0006
这样,协议发送点集中在“区域状态投影器”,业务流程只负责改变区域事实。
响应式区域模型的主要收益:
1.减少推送通知的独立点位。
登录、选角、换区、地下城返回和重连都复用同一个进入区域投影流程。
2.私有空间与共享空间使用同一套协议。
差别只在DesiredView的过滤规则,不需要维护两套人物同步实现。
3.协议顺序稳定。
远端人物始终先0x0002,再0x0165、0x0017,最后0x0018。
4.旧区域清理自然发生。
成员集合变化后重新计算旧区域权威名册,不需要每个换区入口单独记得清理谁。
5.更容易处理延迟和会话替换。
每次投影使用最新区域版本和当前会话身份;旧事件只能触发重算最新状态,不能恢复旧名册。
6.更容易测试。
可以直接给定区域前后状态,断言应产生哪些0x0002、0x0165、0x0017、0x0018、0x0016或0x0006,
不必分别为每个业务入口重新验证整套协议逻辑。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:09 | 显示全部楼层
八、两个玩家的赛丽亚旅馆示例
初始状态:
玩家A:频道1,城镇1,区域0,[gate]
玩家B:频道1,城镇1,区域0,[gate]
虽然两人的channelId、townId和areaId都相同,但有效空间分别为:
A的私人空间:1/1/0/A
B的私人空间:1/1/0/B
服务端分别发送:
给A:0x0018,count=1,成员只有A
给B:0x0018,count=1,成员只有B
A和B之间不发送远端人物建立或移动协议,因此双方互不可见。
当A进入区域1的[normal]区域:
A进入共享空间1/1/1
A收到自己的0x0017和count=1的0x0018
B仍在自己的私人空间,不会看见A
当B随后也进入区域1:
给A发送B的0x0002、0x0165、0x0017,再发送包含A和B的0x0018
给B发送A的0x0002、0x0165、0x0017,再发送包含B和A的0x0018
此时双方才在共享城镇区域互相出现,之后的0x0023移动通过0x0016互相广播。
九、流程摘要
============
选角或返回城镇
->从PVF确定区域类型和落点
->更新权威区域成员状态
->根据接收者计算可见角色集合
->发送远端角色0x0002subtype0
->发送0x0165可见性
->发送0x0017区域和位置
->发送0x0018完整区域名册
区域内移动
->客户端CMD0x0023
->更新区域模型中的位置
->本人和可见同区玩家收到NOTI0x0016
城镇换区
->客户端CMD0x0024
->查询PVF并确定private或shared
->更新新旧区域成员状态
->旧区域发送不含迁移者的0x0018
->新区域执行人物建立和0x0018完整名册流程
赛丽亚私人旅馆
->PVF[gate]
->每角色独立可见空间
->0x0018恒只包含自己
->不向其他同编号旅馆玩家广播人物和移动协议
真正退出世界
->从权威区域状态移除角色
->向仍能看到该角色的客户端发送NOTI0x0006
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:10 | 显示全部楼层
自此,角色如何在区域内看到其他人相关的协议就已经完全覆盖了。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

5380

主题

4万

回帖

16万

积分

管理员

积分
164757
发表于 昨天 03:10 | 显示全部楼层
优秀,请继续。
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:11 | 显示全部楼层
大佬,有服务端端资源吗?[表情:太开心]
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:11 | 显示全部楼层
这是真大佬
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

发表于 昨天 03:12 | 显示全部楼层
不愧是程序员大佬啊
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

发表于 昨天 03:12 | 显示全部楼层
大佬辛苦了
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

发表于 昨天 03:13 | 显示全部楼层
大佬辛苦了
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

6528

主题

5万

回帖

18万

积分

神功绝世

积分
182206
 楼主| 发表于 昨天 03:13 | 显示全部楼层
[表情:真棒]
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

发表于 昨天 03:14 | 显示全部楼层
大佬服务端66[表情:真棒][表情:真棒]
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

发表于 昨天 03:14 | 显示全部楼层
感谢大佬无私分享
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

发表于 昨天 03:15 | 显示全部楼层
牛逼

        🔒 您需要登录才可以查看图片,请 登录注册
   
阿荣社区欢迎你(bbs.vul7.com)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注公众号
Archiver|手机版|小黑屋|阿荣社区 [Arong ! Vul7.com] |nimba_sitemap:appname

相关侵权、举报、投诉及建议等,请发 E-mail:admin@discuz.vip

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.|闽ICP备2022012442号

在本版发帖
关注公众号
QQ客服返回顶部